AccessibilityUIElementGtk.cpp revision f05b935882198ccf7d81675736e3aeb089c5113a
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#include "GOwnPtr.h"
30#include "GRefPtr.h"
31
32#include <JavaScriptCore/JSStringRef.h>
33#include <wtf/Assertions.h>
34
35#include <atk/atk.h>
36#include <gtk/gtk.h>
37
38
39AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
40    : m_element(element)
41{
42}
43
44AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
45    : m_element(other.m_element)
46{
47}
48
49AccessibilityUIElement::~AccessibilityUIElement()
50{
51}
52
53void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elements)
54{
55    // FIXME: implement
56}
57
58void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>&)
59{
60    // FIXME: implement
61}
62
63void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& children)
64{
65    int count = childrenCount();
66    for (int i = 0; i < count; i++) {
67        AtkObject* child = atk_object_ref_accessible_child(ATK_OBJECT(m_element), i);
68        children.append(AccessibilityUIElement(child));
69    }
70}
71
72void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned start, unsigned end)
73{
74    for (unsigned i = start; i < end; i++) {
75        AtkObject* child = atk_object_ref_accessible_child(ATK_OBJECT(m_element), i);
76        elementVector.append(AccessibilityUIElement(child));
77    }
78}
79
80int AccessibilityUIElement::rowCount()
81{
82    if (!m_element)
83        return 0;
84
85    ASSERT(ATK_IS_TABLE(m_element));
86
87    return atk_table_get_n_rows(ATK_TABLE(m_element));
88}
89
90int AccessibilityUIElement::columnCount()
91{
92    if (!m_element)
93        return 0;
94
95    ASSERT(ATK_IS_TABLE(m_element));
96
97    return atk_table_get_n_columns(ATK_TABLE(m_element));
98}
99
100int AccessibilityUIElement::childrenCount()
101{
102    if (!m_element)
103        return 0;
104
105    ASSERT(ATK_IS_OBJECT(m_element));
106
107    return atk_object_get_n_accessible_children(ATK_OBJECT(m_element));
108}
109
110AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
111{
112    // FIXME: implement
113    return 0;
114}
115
116AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
117{
118    // FIXME: implement
119    return 0;
120}
121
122AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
123{
124    Vector<AccessibilityUIElement> children;
125    getChildrenWithRange(children, index, index + 1);
126
127    if (children.size() == 1)
128        return children.at(0);
129
130    return 0;
131}
132
133unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
134{
135    // FIXME: implement
136    return 0;
137}
138
139gchar* attributeSetToString(AtkAttributeSet* attributeSet)
140{
141    GString* str = g_string_new(0);
142    for (GSList* attributes = attributeSet; attributes; attributes = attributes->next) {
143        AtkAttribute* attribute = static_cast<AtkAttribute*>(attributes->data);
144        g_string_append(str, g_strconcat(attribute->name, ":", attribute->value, NULL));
145        if (attributes->next)
146            g_string_append(str, ", ");
147    }
148
149    return g_string_free(str, FALSE);
150}
151
152JSStringRef AccessibilityUIElement::allAttributes()
153{
154    if (!m_element)
155        return JSStringCreateWithCharacters(0, 0);
156
157    ASSERT(ATK_IS_OBJECT(m_element));
158    return JSStringCreateWithUTF8CString(attributeSetToString(atk_object_get_attributes(ATK_OBJECT(m_element))));
159}
160
161JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
162{
163    // FIXME: implement
164    return JSStringCreateWithCharacters(0, 0);
165}
166
167JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
168{
169    // FIXME: implement
170    return JSStringCreateWithCharacters(0, 0);
171}
172
173AccessibilityUIElement AccessibilityUIElement::titleUIElement()
174{
175    // FIXME: implement
176    return 0;
177}
178
179AccessibilityUIElement AccessibilityUIElement::parentElement()
180{
181    if (!m_element)
182        return 0;
183
184    ASSERT(ATK_IS_OBJECT(m_element));
185
186    AtkObject* parent =  atk_object_get_parent(ATK_OBJECT(m_element));
187    return parent ? AccessibilityUIElement(parent) : 0;
188}
189
190JSStringRef AccessibilityUIElement::attributesOfChildren()
191{
192    // FIXME: implement
193    return JSStringCreateWithCharacters(0, 0);
194}
195
196JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
197{
198    // FIXME: implement
199    return JSStringCreateWithCharacters(0, 0);
200}
201
202JSStringRef AccessibilityUIElement::role()
203{
204    AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
205
206    if (!role)
207        return JSStringCreateWithCharacters(0, 0);
208
209    const gchar* roleName = atk_role_get_name(role);
210    GOwnPtr<gchar> axRole(g_strdup_printf("AXRole: %s", roleName));
211
212    return JSStringCreateWithUTF8CString(axRole.get());
213}
214
215JSStringRef AccessibilityUIElement::subrole()
216{
217    return 0;
218}
219
220JSStringRef AccessibilityUIElement::roleDescription()
221{
222    return 0;
223}
224
225JSStringRef AccessibilityUIElement::title()
226{
227    const gchar* name = atk_object_get_name(ATK_OBJECT(m_element));
228
229    if (!name)
230        return JSStringCreateWithCharacters(0, 0);
231
232    GOwnPtr<gchar> axTitle(g_strdup_printf("AXTitle: %s", name));
233
234    return JSStringCreateWithUTF8CString(axTitle.get());
235}
236
237JSStringRef AccessibilityUIElement::description()
238{
239    const gchar* description = atk_object_get_description(ATK_OBJECT(m_element));
240
241    if (!description)
242        return JSStringCreateWithCharacters(0, 0);
243
244    GOwnPtr<gchar> axDesc(g_strdup_printf("AXDescription: %s", description));
245
246    return JSStringCreateWithUTF8CString(axDesc.get());
247}
248
249JSStringRef AccessibilityUIElement::stringValue()
250{
251    // FIXME: implement
252    return JSStringCreateWithCharacters(0, 0);
253}
254
255JSStringRef AccessibilityUIElement::language()
256{
257    // FIXME: implement
258    return JSStringCreateWithCharacters(0, 0);
259}
260
261JSStringRef AccessibilityUIElement::helpText() const
262{
263    return 0;
264}
265
266double AccessibilityUIElement::x()
267{
268    int x, y;
269
270    atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN);
271
272    return x;
273}
274
275double AccessibilityUIElement::y()
276{
277    int x, y;
278
279    atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN);
280
281    return y;
282}
283
284double AccessibilityUIElement::width()
285{
286    int width, height;
287
288    atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
289
290    return width;
291}
292
293double AccessibilityUIElement::height()
294{
295    int width, height;
296
297    atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
298
299    return height;
300}
301
302double AccessibilityUIElement::clickPointX()
303{
304    return 0.f;
305}
306
307double AccessibilityUIElement::clickPointY()
308{
309    return 0.f;
310}
311
312JSStringRef AccessibilityUIElement::orientation() const
313{
314    return 0;
315}
316
317double AccessibilityUIElement::intValue() const
318{
319    GValue value = { 0, { { 0 } } };
320
321    if (!ATK_IS_VALUE(m_element))
322        return 0.0f;
323
324    atk_value_get_current_value(ATK_VALUE(m_element), &value);
325
326    if (G_VALUE_HOLDS_DOUBLE(&value))
327        return g_value_get_double(&value);
328    else if (G_VALUE_HOLDS_INT(&value))
329        return static_cast<double>(g_value_get_int(&value));
330    else
331        return 0.0f;
332}
333
334double AccessibilityUIElement::minValue()
335{
336    GValue value = { 0, { { 0 } } };
337
338    if (!ATK_IS_VALUE(m_element))
339        return 0.0f;
340
341    atk_value_get_minimum_value(ATK_VALUE(m_element), &value);
342
343    if (G_VALUE_HOLDS_DOUBLE(&value))
344        return g_value_get_double(&value);
345    else if (G_VALUE_HOLDS_INT(&value))
346        return static_cast<double>(g_value_get_int(&value));
347    else
348        return 0.0f;
349}
350
351double AccessibilityUIElement::maxValue()
352{
353    GValue value = { 0, { { 0 } } };
354
355    if (!ATK_IS_VALUE(m_element))
356        return 0.0f;
357
358    atk_value_get_maximum_value(ATK_VALUE(m_element), &value);
359
360    if (G_VALUE_HOLDS_DOUBLE(&value))
361        return g_value_get_double(&value);
362    else if (G_VALUE_HOLDS_INT(&value))
363        return static_cast<double>(g_value_get_int(&value));
364    else
365        return 0.0f;
366}
367
368JSStringRef AccessibilityUIElement::valueDescription()
369{
370    // FIXME: implement
371    return JSStringCreateWithCharacters(0, 0);
372}
373
374static bool checkElementState(PlatformUIElement element, AtkStateType stateType)
375{
376    if (!ATK_IS_OBJECT(element))
377         return false;
378
379    PlatformRefPtr<AtkStateSet> stateSet = adoptPlatformRef(atk_object_ref_state_set(ATK_OBJECT(element)));
380    return atk_state_set_contains_state(stateSet.get(), stateType);
381}
382
383bool AccessibilityUIElement::isEnabled()
384{
385    return checkElementState(m_element, ATK_STATE_ENABLED);
386}
387
388int AccessibilityUIElement::insertionPointLineNumber()
389{
390    // FIXME: implement
391    return 0;
392}
393
394bool AccessibilityUIElement::isActionSupported(JSStringRef action)
395{
396    // FIXME: implement
397    return false;
398}
399
400bool AccessibilityUIElement::isRequired() const
401{
402    // FIXME: implement
403    return false;
404}
405
406bool AccessibilityUIElement::isFocused() const
407{
408    if (!ATK_IS_OBJECT(m_element))
409        return false;
410
411    PlatformRefPtr<AtkStateSet> stateSet = adoptPlatformRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
412    gboolean isFocused = atk_state_set_contains_state(stateSet.get(), ATK_STATE_FOCUSED);
413
414    return isFocused;
415}
416
417bool AccessibilityUIElement::isSelected() const
418{
419    return checkElementState(m_element, ATK_STATE_SELECTED);
420}
421
422int AccessibilityUIElement::hierarchicalLevel() const
423{
424    // FIXME: implement
425    return 0;
426}
427
428bool AccessibilityUIElement::ariaIsGrabbed() const
429{
430    return false;
431}
432
433JSStringRef AccessibilityUIElement::ariaDropEffects() const
434{
435    return 0;
436}
437
438bool AccessibilityUIElement::isExpanded() const
439{
440    // FIXME: implement
441    return false;
442}
443
444bool AccessibilityUIElement::isChecked() const
445{
446    return intValue();
447}
448
449JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
450{
451    // FIXME: implement
452    return JSStringCreateWithCharacters(0, 0);
453}
454
455JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
456{
457    // FIXME: implement
458    return JSStringCreateWithCharacters(0, 0);
459}
460
461JSStringRef AccessibilityUIElement::attributesOfColumns()
462{
463    // FIXME: implement
464    return JSStringCreateWithCharacters(0, 0);
465}
466
467JSStringRef AccessibilityUIElement::attributesOfRows()
468{
469    // FIXME: implement
470    return JSStringCreateWithCharacters(0, 0);
471}
472
473JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
474{
475    // FIXME: implement
476    return JSStringCreateWithCharacters(0, 0);
477}
478
479JSStringRef AccessibilityUIElement::attributesOfHeader()
480{
481    // FIXME: implement
482    return JSStringCreateWithCharacters(0, 0);
483}
484
485int AccessibilityUIElement::indexInTable()
486{
487    // FIXME: implement
488    return 0;
489}
490
491JSStringRef AccessibilityUIElement::rowIndexRange()
492{
493    // FIXME: implement
494    return JSStringCreateWithCharacters(0, 0);
495}
496
497JSStringRef AccessibilityUIElement::columnIndexRange()
498{
499    // FIXME: implement
500    return JSStringCreateWithCharacters(0, 0);
501}
502
503int AccessibilityUIElement::lineForIndex(int)
504{
505    // FIXME: implement
506    return 0;
507}
508
509JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
510{
511    // FIXME: implement
512    return JSStringCreateWithCharacters(0, 0);
513}
514
515JSStringRef AccessibilityUIElement::stringForRange(unsigned, unsigned)
516{
517    // FIXME: implement
518    return JSStringCreateWithCharacters(0, 0);
519}
520
521JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned, unsigned)
522{
523    // FIXME: implement
524    return JSStringCreateWithCharacters(0, 0);
525}
526
527bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length)
528{
529    // FIXME: implement
530    return false;
531}
532
533AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned column, unsigned row)
534{
535    // FIXME: implement
536    return 0;
537}
538
539JSStringRef AccessibilityUIElement::selectedTextRange()
540{
541    // FIXME: implement
542    return JSStringCreateWithCharacters(0, 0);
543}
544
545void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
546{
547    // FIXME: implement
548}
549
550JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
551{
552    // FIXME: implement
553    return JSStringCreateWithCharacters(0, 0);
554}
555
556bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
557{
558    // FIXME: implement
559    return false;
560}
561
562bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
563{
564    // FIXME: implement
565    return false;
566}
567
568bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
569{
570    return false;
571}
572
573void AccessibilityUIElement::increment()
574{
575    // FIXME: implement
576}
577
578void AccessibilityUIElement::decrement()
579{
580    // FIXME: implement
581}
582
583void AccessibilityUIElement::press()
584{
585    if (!m_element)
586        return;
587
588    ASSERT(ATK_IS_OBJECT(m_element));
589
590    if (!ATK_IS_ACTION(m_element))
591        return;
592
593    // Only one action per object is supported so far.
594    atk_action_do_action(ATK_ACTION(m_element), 0);
595}
596
597void AccessibilityUIElement::showMenu()
598{
599    // FIXME: implement
600}
601
602AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
603{
604    return 0;
605}
606
607AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
608{
609    return 0;
610}
611
612AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
613{
614    return 0;
615}
616
617AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
618{
619    return 0;
620}
621
622AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
623{
624    return 0;
625}
626
627JSStringRef AccessibilityUIElement::accessibilityValue() const
628{
629    // FIXME: implement
630    return JSStringCreateWithCharacters(0, 0);
631}
632
633JSStringRef AccessibilityUIElement::documentEncoding()
634{
635    AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
636    if (role != ATK_ROLE_DOCUMENT_FRAME)
637        return JSStringCreateWithCharacters(0, 0);
638
639    return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element), "Encoding"));
640}
641
642JSStringRef AccessibilityUIElement::documentURI()
643{
644    AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
645    if (role != ATK_ROLE_DOCUMENT_FRAME)
646        return JSStringCreateWithCharacters(0, 0);
647
648    return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element), "URI"));
649}
650
651JSStringRef AccessibilityUIElement::url()
652{
653    // FIXME: implement
654    return JSStringCreateWithCharacters(0, 0);
655}
656
657bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
658{
659    // FIXME: implement
660    return false;
661}
662
663void AccessibilityUIElement::removeNotificationListener()
664{
665    // FIXME: implement
666}
667
668bool AccessibilityUIElement::isFocusable() const
669{
670    if (!ATK_IS_OBJECT(m_element))
671        return false;
672
673    PlatformRefPtr<AtkStateSet> stateSet = adoptPlatformRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
674    gboolean isFocusable = atk_state_set_contains_state(stateSet.get(), ATK_STATE_FOCUSABLE);
675
676    return isFocusable;
677}
678
679bool AccessibilityUIElement::isSelectable() const
680{
681    // FIXME: implement
682    return false;
683}
684
685bool AccessibilityUIElement::isMultiSelectable() const
686{
687    // FIXME: implement
688    return false;
689}
690
691bool AccessibilityUIElement::isVisible() const
692{
693    // FIXME: implement
694    return false;
695}
696
697bool AccessibilityUIElement::isOffScreen() const
698{
699    // FIXME: implement
700    return false;
701}
702
703bool AccessibilityUIElement::isCollapsed() const
704{
705    // FIXME: implement
706    return false;
707}
708
709bool AccessibilityUIElement::isIgnored() const
710{
711    // FIXME: implement
712    return false;
713}
714
715bool AccessibilityUIElement::hasPopup() const
716{
717    // FIXME: implement
718    return false;
719}
720
721void AccessibilityUIElement::takeFocus()
722{
723    // FIXME: implement
724}
725
726void AccessibilityUIElement::takeSelection()
727{
728    // FIXME: implement
729}
730
731void AccessibilityUIElement::addSelection()
732{
733    // FIXME: implement
734}
735
736void AccessibilityUIElement::removeSelection()
737{
738    // FIXME: implement
739}
740