[GTK] accessibility/aria-scrollbar-role.html is failing
[WebKit-https.git] / Tools / DumpRenderTree / atk / AccessibilityUIElementAtk.cpp
1 /*
2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3  * Copyright (C) 2009 Jan Michael Alonzo
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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. 
25  */
26
27 #include "config.h"
28 #include "AccessibilityUIElement.h"
29
30 #if HAVE(ACCESSIBILITY)
31
32 #include <JavaScriptCore/JSStringRef.h>
33 #include <atk/atk.h>
34 #include <wtf/Assertions.h>
35 #include <wtf/gobject/GOwnPtr.h>
36 #include <wtf/gobject/GRefPtr.h>
37 #include <wtf/text/CString.h>
38 #include <wtf/text/WTFString.h>
39 #include <wtf/unicode/CharacterNames.h>
40
41 static String coreAttributeToAtkAttribute(JSStringRef attribute)
42 {
43     size_t bufferSize = JSStringGetMaximumUTF8CStringSize(attribute);
44     GOwnPtr<gchar> buffer(static_cast<gchar*>(g_malloc(bufferSize)));
45     JSStringGetUTF8CString(attribute, buffer.get(), bufferSize);
46
47     String attributeString = String::fromUTF8(buffer.get());
48     if (attributeString == "AXPlaceholderValue")
49         return "placeholder-text";
50
51     return "";
52 }
53
54 static inline String roleToString(AtkRole role)
55 {
56     switch (role) {
57     case ATK_ROLE_ALERT:
58         return "AXRole: AXAlert";
59     case ATK_ROLE_CANVAS:
60         return "AXRole: AXCanvas";
61     case ATK_ROLE_CHECK_BOX:
62         return "AXRole: AXCheckBox";
63     case ATK_ROLE_COLUMN_HEADER:
64         return "AXRole: AXColumnHeader";
65     case ATK_ROLE_COMBO_BOX:
66         return "AXRole: AXComboBox";
67     case ATK_ROLE_DOCUMENT_FRAME:
68         return "AXRole: AXWebArea";
69     case ATK_ROLE_ENTRY:
70         return "AXRole: AXTextField";
71     case ATK_ROLE_FOOTER:
72         return "AXRole: AXFooter";
73     case ATK_ROLE_FORM:
74         return "AXRole: AXForm";
75     case ATK_ROLE_GROUPING:
76         return "AXRole: AXGroup";
77     case ATK_ROLE_HEADING:
78         return "AXRole: AXHeading";
79     case ATK_ROLE_IMAGE:
80         return "AXRole: AXImage";
81     case ATK_ROLE_IMAGE_MAP:
82         return "AXRole: AXImageMap";
83     case ATK_ROLE_LABEL:
84         return "AXRole: AXLabel";
85     case ATK_ROLE_LINK:
86         return "AXRole: AXLink";
87     case ATK_ROLE_LIST:
88         return "AXRole: AXList";
89     case ATK_ROLE_LIST_BOX:
90         return "AXRole: AXListBox";
91     case ATK_ROLE_LIST_ITEM:
92         return "AXRole: AXListItem";
93     case ATK_ROLE_MENU:
94         return "AXRole: AXMenu";
95     case ATK_ROLE_MENU_BAR:
96         return "AXRole: AXMenuBar";
97     case ATK_ROLE_MENU_ITEM:
98         return "AXRole: AXMenuItem";
99     case ATK_ROLE_PAGE_TAB:
100         return "AXRole: AXTab";
101     case ATK_ROLE_PAGE_TAB_LIST:
102         return "AXRole: AXTabGroup";
103     case ATK_ROLE_PANEL:
104         return "AXRole: AXGroup";
105     case ATK_ROLE_PARAGRAPH:
106         return "AXRole: AXParagraph";
107     case ATK_ROLE_PASSWORD_TEXT:
108         return "AXRole: AXPasswordField";
109     case ATK_ROLE_PUSH_BUTTON:
110         return "AXRole: AXButton";
111     case ATK_ROLE_RADIO_BUTTON:
112         return "AXRole: AXRadioButton";
113     case ATK_ROLE_ROW_HEADER:
114         return "AXRole: AXRowHeader";
115     case ATK_ROLE_RULER:
116         return "AXRole: AXRuler";
117     case ATK_ROLE_SCROLL_BAR:
118         return "AXRole: AXScrollBar";
119     case ATK_ROLE_SCROLL_PANE:
120         return "AXRole: AXScrollArea";
121     case ATK_ROLE_SECTION:
122         return "AXRole: AXDiv";
123     case ATK_ROLE_SEPARATOR:
124         return "AXRole: AXHorizontalRule";
125     case ATK_ROLE_SLIDER:
126         return "AXRole: AXSlider";
127     case ATK_ROLE_SPIN_BUTTON:
128         return "AXRole: AXSpinButton";
129     case ATK_ROLE_TABLE:
130         return "AXRole: AXTable";
131     case ATK_ROLE_TABLE_CELL:
132         return "AXRole: AXCell";
133     case ATK_ROLE_TABLE_COLUMN_HEADER:
134         return "AXRole: AXColumnHeader";
135     case ATK_ROLE_TABLE_ROW:
136         return "AXRole: AXRow";
137     case ATK_ROLE_TABLE_ROW_HEADER:
138         return "AXRole: AXRowHeader";
139     case ATK_ROLE_TOGGLE_BUTTON:
140         return "AXRole: AXToggleButton";
141     case ATK_ROLE_TOOL_BAR:
142         return "AXRole: AXToolbar";
143     case ATK_ROLE_TOOL_TIP:
144         return "AXRole: AXUserInterfaceTooltip";
145     case ATK_ROLE_TREE:
146         return "AXRole: AXTree";
147     case ATK_ROLE_TREE_TABLE:
148         return "AXRole: AXTreeGrid";
149     case ATK_ROLE_TREE_ITEM:
150         return "AXRole: AXTreeItem";
151     case ATK_ROLE_WINDOW:
152         return "AXRole: AXWindow";
153     case ATK_ROLE_UNKNOWN:
154         return "AXRole: AXUnknown";
155     default:
156         // We want to distinguish ATK_ROLE_UNKNOWN from a known AtkRole which
157         // our DRT isn't properly handling.
158         return "AXRole: FIXME not identified";
159     }
160 }
161
162 static inline gchar* replaceCharactersForResults(gchar* str)
163 {
164     String uString = String::fromUTF8(str);
165
166     // The object replacement character is passed along to ATs so we need to be
167     // able to test for their presence and do so without causing test failures.
168     uString.replace(objectReplacementCharacter, "<obj>");
169
170     // The presence of newline characters in accessible text of a single object
171     // is appropriate, but it makes test results (especially the accessible tree)
172     // harder to read.
173     uString.replace("\n", "<\\n>");
174
175     return g_strdup(uString.utf8().data());
176 }
177
178 static bool checkElementState(PlatformUIElement element, AtkStateType stateType)
179 {
180     if (!ATK_IS_OBJECT(element))
181         return false;
182
183     GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(element)));
184     return atk_state_set_contains_state(stateSet.get(), stateType);
185 }
186
187 AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
188     : m_element(element)
189 {
190     if (m_element)
191         g_object_ref(m_element);
192 }
193
194 AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
195     : m_element(other.m_element)
196 {
197     if (m_element)
198         g_object_ref(m_element);
199 }
200
201 AccessibilityUIElement::~AccessibilityUIElement()
202 {
203     if (m_element)
204         g_object_unref(m_element);
205 }
206
207 void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elements)
208 {
209     // FIXME: implement
210 }
211
212 void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>&)
213 {
214     // FIXME: implement
215 }
216
217 void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& children)
218 {
219     int count = childrenCount();
220     for (int i = 0; i < count; i++) {
221         AtkObject* child = atk_object_ref_accessible_child(ATK_OBJECT(m_element), i);
222         children.append(AccessibilityUIElement(child));
223     }
224 }
225
226 void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned start, unsigned end)
227 {
228     for (unsigned i = start; i < end; i++) {
229         AtkObject* child = atk_object_ref_accessible_child(ATK_OBJECT(m_element), i);
230         elementVector.append(AccessibilityUIElement(child));
231     }
232 }
233
234 int AccessibilityUIElement::rowCount()
235 {
236     if (!m_element)
237         return 0;
238
239     ASSERT(ATK_IS_TABLE(m_element));
240
241     return atk_table_get_n_rows(ATK_TABLE(m_element));
242 }
243
244 int AccessibilityUIElement::columnCount()
245 {
246     if (!m_element)
247         return 0;
248
249     ASSERT(ATK_IS_TABLE(m_element));
250
251     return atk_table_get_n_columns(ATK_TABLE(m_element));
252 }
253
254 int AccessibilityUIElement::childrenCount()
255 {
256     if (!m_element)
257         return 0;
258
259     ASSERT(ATK_IS_OBJECT(m_element));
260
261     return atk_object_get_n_accessible_children(ATK_OBJECT(m_element));
262 }
263
264 AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
265 {
266     if (!m_element)
267         return 0;
268
269     return AccessibilityUIElement(atk_component_ref_accessible_at_point(ATK_COMPONENT(m_element), x, y, ATK_XY_WINDOW));
270 }
271
272 AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
273 {
274     // FIXME: implement
275     return 0;
276 }
277
278 AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
279 {
280     Vector<AccessibilityUIElement> children;
281     getChildrenWithRange(children, index, index + 1);
282
283     if (children.size() == 1)
284         return children.at(0);
285
286     return 0;
287 }
288
289 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
290
291     // FIXME: implement
292     return 0;
293 }
294
295 gchar* attributeSetToString(AtkAttributeSet* attributeSet)
296 {
297     GString* str = g_string_new(0);
298     for (GSList* attributes = attributeSet; attributes; attributes = attributes->next) {
299         AtkAttribute* attribute = static_cast<AtkAttribute*>(attributes->data);
300         GOwnPtr<gchar> attributeData(g_strconcat(attribute->name, ":", attribute->value, NULL));
301         g_string_append(str, attributeData.get());
302         if (attributes->next)
303             g_string_append(str, ", ");
304     }
305
306     return g_string_free(str, FALSE);
307 }
308
309 JSStringRef AccessibilityUIElement::allAttributes()
310 {
311     if (!m_element)
312         return JSStringCreateWithCharacters(0, 0);
313
314     ASSERT(ATK_IS_OBJECT(m_element));
315     GOwnPtr<gchar> attributeData(attributeSetToString(atk_object_get_attributes(ATK_OBJECT(m_element))));
316     return JSStringCreateWithUTF8CString(attributeData.get());
317 }
318
319 JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
320 {
321     // FIXME: implement
322     return JSStringCreateWithCharacters(0, 0);
323 }
324
325 JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
326 {
327     // FIXME: implement
328     return JSStringCreateWithCharacters(0, 0);
329 }
330
331 AccessibilityUIElement AccessibilityUIElement::titleUIElement()
332 {
333     if (!m_element)
334         return 0;
335
336     AtkRelationSet* set = atk_object_ref_relation_set(ATK_OBJECT(m_element));
337     if (!set)
338         return 0;
339
340     AtkObject* target = 0;
341     int count = atk_relation_set_get_n_relations(set);
342     for (int i = 0; i < count; i++) {
343         AtkRelation* relation = atk_relation_set_get_relation(set, i);
344         if (atk_relation_get_relation_type(relation) == ATK_RELATION_LABELLED_BY) {
345             GPtrArray* targetList = atk_relation_get_target(relation);
346             if (targetList->len)
347                 target = static_cast<AtkObject*>(g_ptr_array_index(targetList, 0));
348         }
349     }
350
351     g_object_unref(set);
352     return target ? AccessibilityUIElement(target) : 0;
353 }
354
355 AccessibilityUIElement AccessibilityUIElement::parentElement()
356 {
357     if (!m_element)
358         return 0;
359
360     ASSERT(ATK_IS_OBJECT(m_element));
361
362     AtkObject* parent =  atk_object_get_parent(ATK_OBJECT(m_element));
363     return parent ? AccessibilityUIElement(parent) : 0;
364 }
365
366 JSStringRef AccessibilityUIElement::attributesOfChildren()
367 {
368     // FIXME: implement
369     return JSStringCreateWithCharacters(0, 0);
370 }
371
372 JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
373 {
374     // FIXME: implement
375     return JSStringCreateWithCharacters(0, 0);
376 }
377
378 JSStringRef AccessibilityUIElement::role()
379 {
380     AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
381     if (!role)
382         return JSStringCreateWithCharacters(0, 0);
383
384     String roleString = roleToString(role);
385     return JSStringCreateWithUTF8CString(roleString.utf8().data());
386 }
387
388 JSStringRef AccessibilityUIElement::subrole()
389 {
390     return 0;
391 }
392
393 JSStringRef AccessibilityUIElement::roleDescription()
394 {
395     return 0;
396 }
397
398 JSStringRef AccessibilityUIElement::title()
399 {
400     const gchar* name = atk_object_get_name(ATK_OBJECT(m_element));
401     GOwnPtr<gchar> axTitle(g_strdup_printf("AXTitle: %s", name ? name : ""));
402
403     return JSStringCreateWithUTF8CString(axTitle.get());
404 }
405
406 JSStringRef AccessibilityUIElement::description()
407 {
408     const gchar* description = atk_object_get_description(ATK_OBJECT(m_element));
409
410     if (!description)
411         return JSStringCreateWithCharacters(0, 0);
412
413     GOwnPtr<gchar> axDesc(g_strdup_printf("AXDescription: %s", description));
414
415     return JSStringCreateWithUTF8CString(axDesc.get());
416 }
417
418 JSStringRef AccessibilityUIElement::stringValue()
419 {
420     if (!m_element || !ATK_IS_TEXT(m_element))
421         return JSStringCreateWithCharacters(0, 0);
422
423     gchar* text = atk_text_get_text(ATK_TEXT(m_element), 0, -1);
424     GOwnPtr<gchar> axValue(g_strdup_printf("AXValue: %s", replaceCharactersForResults(text)));
425     g_free(text);
426
427     return JSStringCreateWithUTF8CString(axValue.get());
428 }
429
430 JSStringRef AccessibilityUIElement::language()
431 {
432     if (!m_element)
433         return JSStringCreateWithCharacters(0, 0);
434
435     // In ATK, the document language is exposed as the document's locale.
436     if (atk_object_get_role(ATK_OBJECT(m_element)) == ATK_ROLE_DOCUMENT_FRAME)
437         return JSStringCreateWithUTF8CString(g_strdup_printf("AXLanguage: %s", atk_document_get_locale(ATK_DOCUMENT(m_element))));
438
439     // For all other objects, the language is exposed as an AtkText attribute.
440     if (!ATK_IS_TEXT(m_element))
441         return JSStringCreateWithCharacters(0, 0);
442
443     for (GSList* textAttributes = atk_text_get_default_attributes(ATK_TEXT(m_element)); textAttributes; textAttributes = textAttributes->next) {
444         AtkAttribute* atkAttribute = static_cast<AtkAttribute*>(textAttributes->data);
445         if (!strcmp(atkAttribute->name, atk_text_attribute_get_name(ATK_TEXT_ATTR_LANGUAGE)))
446             return JSStringCreateWithUTF8CString(g_strdup_printf("AXLanguage: %s", atkAttribute->value));
447     }
448
449     return JSStringCreateWithCharacters(0, 0);
450 }
451
452 double AccessibilityUIElement::x()
453 {
454     int x, y;
455
456     atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN);
457
458     return x;
459 }
460
461 double AccessibilityUIElement::y()
462 {
463     int x, y;
464
465     atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN);
466
467     return y;
468 }
469
470 double AccessibilityUIElement::width()
471 {
472     int width, height;
473
474     atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
475
476     return width;
477 }
478
479 double AccessibilityUIElement::height()
480 {
481     int width, height;
482
483     atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
484
485     return height;
486 }
487
488 double AccessibilityUIElement::clickPointX()
489 {
490     // Note: This is not something we have in ATK.
491     return 0.f;
492 }
493
494 double AccessibilityUIElement::clickPointY()
495 {
496     // Note: This is not something we have in ATK.
497     return 0.f;
498 }
499
500 JSStringRef AccessibilityUIElement::orientation() const
501 {
502     if (!m_element || !ATK_IS_OBJECT(m_element))
503         return JSStringCreateWithCharacters(0, 0);
504
505     const char* axOrientation = 0;
506     if (checkElementState(m_element, ATK_STATE_HORIZONTAL))
507         axOrientation = "AXOrientation: AXHorizontalOrientation";
508     else if (checkElementState(m_element, ATK_STATE_VERTICAL))
509         axOrientation = "AXOrientation: AXVerticalOrientation";
510
511     if (!axOrientation)
512         return JSStringCreateWithCharacters(0, 0);
513
514     return JSStringCreateWithUTF8CString(axOrientation);
515 }
516
517 double AccessibilityUIElement::intValue() const
518 {
519     GValue value = { 0, { { 0 } } };
520
521     if (!ATK_IS_VALUE(m_element))
522         return 0.0f;
523
524     atk_value_get_current_value(ATK_VALUE(m_element), &value);
525     if (!G_VALUE_HOLDS_FLOAT(&value))
526         return 0.0f;
527     return g_value_get_float(&value);
528 }
529
530 double AccessibilityUIElement::minValue()
531 {
532     GValue value = { 0, { { 0 } } };
533
534     if (!ATK_IS_VALUE(m_element))
535         return 0.0f;
536
537     atk_value_get_minimum_value(ATK_VALUE(m_element), &value);
538     if (!G_VALUE_HOLDS_FLOAT(&value))
539         return 0.0f;
540     return g_value_get_float(&value);
541 }
542
543 double AccessibilityUIElement::maxValue()
544 {
545     GValue value = { 0, { { 0 } } };
546
547     if (!ATK_IS_VALUE(m_element))
548         return 0.0f;
549
550     atk_value_get_maximum_value(ATK_VALUE(m_element), &value);
551     if (!G_VALUE_HOLDS_FLOAT(&value))
552         return 0.0f;
553     return g_value_get_float(&value);
554 }
555
556 JSStringRef AccessibilityUIElement::valueDescription()
557 {
558     // FIXME: implement after it has been implemented in ATK.
559     // See: https://bugzilla.gnome.org/show_bug.cgi?id=684576
560     return JSStringCreateWithCharacters(0, 0);
561 }
562
563 bool AccessibilityUIElement::isEnabled()
564 {
565     return checkElementState(m_element, ATK_STATE_ENABLED);
566 }
567
568 int AccessibilityUIElement::insertionPointLineNumber()
569 {
570     // FIXME: implement
571     return 0;
572 }
573
574 bool AccessibilityUIElement::isPressActionSupported()
575 {
576     // FIXME: implement
577     return false;
578 }
579
580 bool AccessibilityUIElement::isIncrementActionSupported()
581 {
582     // FIXME: implement
583     return false;
584 }
585
586 bool AccessibilityUIElement::isDecrementActionSupported()
587 {
588     // FIXME: implement
589     return false;
590 }
591
592 bool AccessibilityUIElement::isRequired() const
593 {
594     // FIXME: implement
595     return false;
596 }
597
598 bool AccessibilityUIElement::isFocused() const
599 {
600     if (!ATK_IS_OBJECT(m_element))
601         return false;
602
603     GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
604     gboolean isFocused = atk_state_set_contains_state(stateSet.get(), ATK_STATE_FOCUSED);
605
606     return isFocused;
607 }
608
609 bool AccessibilityUIElement::isSelected() const
610 {
611     return checkElementState(m_element, ATK_STATE_SELECTED);
612 }
613
614 int AccessibilityUIElement::hierarchicalLevel() const
615 {
616     // FIXME: implement
617     return 0;
618 }
619
620 bool AccessibilityUIElement::ariaIsGrabbed() const
621 {
622     return false;
623 }
624
625 JSStringRef AccessibilityUIElement::ariaDropEffects() const
626 {   
627     return 0; 
628 }
629
630 bool AccessibilityUIElement::isExpanded() const
631 {
632     if (!ATK_IS_OBJECT(m_element))
633         return false;
634
635     GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
636     gboolean isExpanded = atk_state_set_contains_state(stateSet.get(), ATK_STATE_EXPANDED);
637
638     return isExpanded;
639 }
640
641 bool AccessibilityUIElement::isChecked() const
642 {
643     if (!ATK_IS_OBJECT(m_element))
644         return false;
645
646     GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
647     gboolean isChecked = atk_state_set_contains_state(stateSet.get(), ATK_STATE_CHECKED);
648
649     return isChecked;
650 }
651
652 JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
653 {
654     // FIXME: implement
655     return JSStringCreateWithCharacters(0, 0);
656 }
657
658 JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
659 {
660     // FIXME: implement
661     return JSStringCreateWithCharacters(0, 0);
662 }
663
664 JSStringRef AccessibilityUIElement::attributesOfColumns()
665 {
666     // FIXME: implement
667     return JSStringCreateWithCharacters(0, 0);
668 }
669
670 JSStringRef AccessibilityUIElement::attributesOfRows()
671 {
672     // FIXME: implement
673     return JSStringCreateWithCharacters(0, 0);
674 }
675
676 JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
677 {
678     // FIXME: implement
679     return JSStringCreateWithCharacters(0, 0);
680 }
681
682 JSStringRef AccessibilityUIElement::attributesOfHeader()
683 {
684     // FIXME: implement
685     return JSStringCreateWithCharacters(0, 0);
686 }
687
688 int AccessibilityUIElement::indexInTable()
689 {
690     // FIXME: implement
691     return 0;
692 }
693
694 static JSStringRef indexRangeInTable(PlatformUIElement element, bool isRowRange)
695 {
696     GOwnPtr<gchar> rangeString(g_strdup("{0, 0}"));
697
698     if (!element)
699         return JSStringCreateWithUTF8CString(rangeString.get());
700
701     ASSERT(ATK_IS_OBJECT(element));
702
703     AtkObject* axTable = atk_object_get_parent(ATK_OBJECT(element));
704     if (!axTable || !ATK_IS_TABLE(axTable))
705         return JSStringCreateWithUTF8CString(rangeString.get());
706
707     // Look for the cell in the table.
708     gint indexInParent = atk_object_get_index_in_parent(ATK_OBJECT(element));
709     if (indexInParent == -1)
710         return JSStringCreateWithUTF8CString(rangeString.get());
711
712     int row = -1;
713     int column = -1;
714     row = atk_table_get_row_at_index(ATK_TABLE(axTable), indexInParent);
715     column = atk_table_get_column_at_index(ATK_TABLE(axTable), indexInParent);
716
717     // Get the actual values, if row and columns are valid values.
718     if (row != -1 && column != -1) {
719         int base = 0;
720         int length = 0;
721         if (isRowRange) {
722             base = row;
723             length = atk_table_get_row_extent_at(ATK_TABLE(axTable), row, column);
724         } else {
725             base = column;
726             length = atk_table_get_column_extent_at(ATK_TABLE(axTable), row, column);
727         }
728         rangeString.set(g_strdup_printf("{%d, %d}", base, length));
729     }
730
731     return JSStringCreateWithUTF8CString(rangeString.get());
732 }
733
734 JSStringRef AccessibilityUIElement::rowIndexRange()
735 {
736     // Range in table for rows.
737     return indexRangeInTable(m_element, true);
738 }
739
740 JSStringRef AccessibilityUIElement::columnIndexRange()
741 {
742     // Range in table for columns.
743     return indexRangeInTable(m_element, false);
744 }
745
746 int AccessibilityUIElement::lineForIndex(int)
747 {
748     // FIXME: implement
749     return 0;
750 }
751
752 JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
753 {
754     // FIXME: implement
755     return JSStringCreateWithCharacters(0, 0);
756 }
757
758 JSStringRef AccessibilityUIElement::stringForRange(unsigned, unsigned) 
759 {
760     // FIXME: implement
761     return JSStringCreateWithCharacters(0, 0);
762
763
764 JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned, unsigned)
765 {
766     // FIXME: implement
767     return JSStringCreateWithCharacters(0, 0);
768 }
769
770 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length)
771 {
772     // FIXME: implement
773     return false;
774 }
775
776 AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(AccessibilityUIElement* startElement, bool isDirectionNext, JSStringRef searchKey, JSStringRef searchText)
777 {
778     // FIXME: implement
779     return 0;
780 }
781
782 AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned column, unsigned row)
783 {
784     if (!m_element)
785         return 0;
786
787     ASSERT(ATK_IS_TABLE(m_element));
788
789     // Adopt the AtkObject representing the cell because
790     // at_table_ref_at() transfers full ownership.
791     GRefPtr<AtkObject> foundCell = adoptGRef(atk_table_ref_at(ATK_TABLE(m_element), row, column));
792     return foundCell ? AccessibilityUIElement(foundCell.get()) : 0;
793 }
794
795 JSStringRef AccessibilityUIElement::selectedTextRange()
796 {
797     // FIXME: implement
798     return JSStringCreateWithCharacters(0, 0);
799 }
800
801 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
802 {
803     // FIXME: implement
804 }
805
806 JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
807 {
808     if (!m_element)
809         return JSStringCreateWithCharacters(0, 0);
810
811     String atkAttributeName = coreAttributeToAtkAttribute(attribute);
812     if (atkAttributeName.isEmpty())
813         return JSStringCreateWithCharacters(0, 0);
814
815     for (GSList* atkAttributes = atk_object_get_attributes(ATK_OBJECT(m_element)); atkAttributes; atkAttributes = atkAttributes->next) {
816         AtkAttribute* atkAttribute = static_cast<AtkAttribute*>(atkAttributes->data);
817         if (!strcmp(atkAttribute->name, atkAttributeName.utf8().data()))
818             return JSStringCreateWithUTF8CString(atkAttribute->value);
819     }
820
821     return JSStringCreateWithCharacters(0, 0);
822 }
823
824 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
825 {
826     // FIXME: implement
827     return 0.0f;
828 }
829
830 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
831 {
832     // FIXME: implement
833     return false;
834 }
835
836 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
837 {
838     // FIXME: implement
839     return false;
840 }
841
842 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
843 {
844     return false;
845 }
846
847 static void alterCurrentValue(PlatformUIElement element, int factor)
848 {
849     if (!element)
850         return;
851
852     ASSERT(ATK_IS_VALUE(element));
853
854     GValue currentValue = G_VALUE_INIT;
855     atk_value_get_current_value(ATK_VALUE(element), &currentValue);
856
857     GValue increment = G_VALUE_INIT;
858     atk_value_get_minimum_increment(ATK_VALUE(element), &increment);
859
860     GValue newValue = G_VALUE_INIT;
861     g_value_init(&newValue, G_TYPE_FLOAT);
862
863     g_value_set_float(&newValue, g_value_get_float(&currentValue) + factor * g_value_get_float(&increment));
864     atk_value_set_current_value(ATK_VALUE(element), &newValue);
865
866     g_value_unset(&newValue);
867     g_value_unset(&increment);
868     g_value_unset(&currentValue);
869 }
870
871 void AccessibilityUIElement::increment()
872 {
873     alterCurrentValue(m_element, 1);
874 }
875
876 void AccessibilityUIElement::decrement()
877 {
878     alterCurrentValue(m_element, -1);
879 }
880
881 void AccessibilityUIElement::press()
882 {
883     if (!m_element)
884         return;
885
886     ASSERT(ATK_IS_OBJECT(m_element));
887
888     if (!ATK_IS_ACTION(m_element))
889         return;
890
891     // Only one action per object is supported so far.
892     atk_action_do_action(ATK_ACTION(m_element), 0);
893 }
894
895 void AccessibilityUIElement::showMenu()
896 {
897     // FIXME: implement
898 }
899
900 AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
901 {
902     return 0;
903 }
904
905 AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
906 {
907     return 0;
908 }
909
910 AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
911 {
912     return 0;
913 }
914
915 AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
916 {
917     return 0;
918 }
919
920 AccessibilityUIElement AccessibilityUIElement::rowAtIndex(unsigned index)
921 {
922     return 0;
923 }
924
925 AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
926 {
927     return 0;
928 }
929
930 JSStringRef AccessibilityUIElement::accessibilityValue() const
931 {
932     // FIXME: implement
933     return JSStringCreateWithCharacters(0, 0);
934 }
935
936 JSStringRef AccessibilityUIElement::documentEncoding()
937 {
938     AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
939     if (role != ATK_ROLE_DOCUMENT_FRAME)
940         return JSStringCreateWithCharacters(0, 0);
941
942     return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element), "Encoding"));
943 }
944
945 JSStringRef AccessibilityUIElement::documentURI()
946 {
947     AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
948     if (role != ATK_ROLE_DOCUMENT_FRAME)
949         return JSStringCreateWithCharacters(0, 0);
950
951     return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element), "URI"));
952 }
953
954 JSStringRef AccessibilityUIElement::url()
955 {
956     // FIXME: implement
957     return JSStringCreateWithCharacters(0, 0);
958 }
959
960 bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
961 {
962     // FIXME: implement
963     return false;
964 }
965
966 void AccessibilityUIElement::removeNotificationListener()
967 {
968     // FIXME: implement
969 }
970
971 bool AccessibilityUIElement::isFocusable() const
972 {
973     if (!ATK_IS_OBJECT(m_element))
974         return false;
975
976     GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
977     gboolean isFocusable = atk_state_set_contains_state(stateSet.get(), ATK_STATE_FOCUSABLE);
978
979     return isFocusable;
980 }
981
982 bool AccessibilityUIElement::isSelectable() const
983 {
984     return checkElementState(m_element, ATK_STATE_SELECTABLE);
985 }
986
987 bool AccessibilityUIElement::isMultiSelectable() const
988 {
989     return checkElementState(m_element, ATK_STATE_MULTISELECTABLE);
990 }
991
992 bool AccessibilityUIElement::isSelectedOptionActive() const
993 {
994     // FIXME: implement
995     return false;
996 }
997
998 bool AccessibilityUIElement::isVisible() const
999 {
1000     // FIXME: implement
1001     return false;
1002 }
1003
1004 bool AccessibilityUIElement::isOffScreen() const
1005 {
1006     // FIXME: implement
1007     return false;
1008 }
1009
1010 bool AccessibilityUIElement::isCollapsed() const
1011 {
1012     // FIXME: implement
1013     return false;
1014 }
1015
1016 bool AccessibilityUIElement::isIgnored() const
1017 {
1018     // FIXME: implement
1019     return false;
1020 }
1021
1022 bool AccessibilityUIElement::hasPopup() const
1023 {
1024     // FIXME: implement
1025     return false;
1026 }
1027
1028 void AccessibilityUIElement::takeFocus()
1029 {
1030     // FIXME: implement
1031 }
1032
1033 void AccessibilityUIElement::takeSelection()
1034 {
1035     // FIXME: implement
1036 }
1037
1038 void AccessibilityUIElement::addSelection()
1039 {
1040     // FIXME: implement
1041 }
1042
1043 void AccessibilityUIElement::removeSelection()
1044 {
1045     // FIXME: implement
1046 }
1047
1048 void AccessibilityUIElement::scrollToMakeVisible()
1049 {
1050     // FIXME: implement
1051 }
1052
1053 void AccessibilityUIElement::scrollToMakeVisibleWithSubFocus(int x, int y, int width, int height)
1054 {
1055     // FIXME: implement
1056 }
1057
1058 void AccessibilityUIElement::scrollToGlobalPoint(int x, int y)
1059 {
1060     // FIXME: implement
1061 }
1062
1063 #endif