summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/accessibility/gtk/AccessibilityObjectAtk.cpp
blob: 42cf02ed532be8fd9c9d43c7513be619618c70d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/*
 * Copyright (C) 2008 Apple Ltd.
 * Copyright (C) 2008 Alp Toker <alp@atoker.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "config.h"
#include "AccessibilityObject.h"

#include "RenderObject.h"
#include "RenderText.h"
#include <glib-object.h>

#if HAVE(ACCESSIBILITY)

namespace WebCore {

bool AccessibilityObject::accessibilityIgnoreAttachment() const
{
    return false;
}

AccessibilityObjectInclusion AccessibilityObject::accessibilityPlatformIncludesObject() const
{
    AccessibilityObject* parent = parentObject();
    if (!parent)
        return DefaultBehavior;

    AccessibilityRole role = roleValue();
    if (role == HorizontalRuleRole)
        return IncludeObject;

    // We expose the slider as a whole but not its value indicator.
    if (role == SliderThumbRole)
        return IgnoreObject;

    // When a list item is made up entirely of children (e.g. paragraphs)
    // the list item gets ignored. We need it.
    if (isGroup() && parent->isList())
        return IncludeObject;

    // Entries and password fields have extraneous children which we want to ignore.
    if (parent->isPasswordField() || parent->isTextControl())
        return IgnoreObject;

    // Include all tables, even layout tables. The AT can decide what to do with each.
    if (role == CellRole || role == TableRole)
        return IncludeObject;

    // The object containing the text should implement AtkText itself.
    if (role == StaticTextRole)
        return IgnoreObject;

    // Include all list items, regardless they have or not inline children
    if (role == ListItemRole)
        return IncludeObject;

    // Bullets/numbers for list items shouldn't be exposed as AtkObjects.
    if (role == ListMarkerRole)
        return IgnoreObject;

    // Never expose an unknown object, since AT's won't know what to
    // do with them. This is what is done on the Mac as well.
    if (role == UnknownRole)
        return IgnoreObject;

    // Given a paragraph or div containing a non-nested anonymous block, WebCore
    // ignores the paragraph or div and includes the block. We want the opposite:
    // ATs are expecting accessible objects associated with textual elements. They
    // usually have no need for the anonymous block. And when the wrong objects
    // get included or ignored, needed accessibility signals do not get emitted.
    if (role == ParagraphRole || role == DivRole) {
        AccessibilityObject* child = firstAnonymousBlockChild();
        if (!child)
            return DefaultBehavior;

        child = child->firstChild();
        if (child && (child->isLink() || !child->firstAnonymousBlockChild()))
            return IncludeObject;
    }

    // Block spans result in objects of ATK_ROLE_PANEL which are almost always unwanted.
    // However, if we ignore block spans whose parent is the body, the child controls
    // will become immediate children of the ATK_ROLE_DOCUMENT_FRAME and any text will
    // become text within the document frame itself. This ultimately may be what we want
    // and would largely be consistent with what we see from Gecko. However, ignoring
    // spans whose parent is the body changes the current behavior we see from WebCore.
    // Until we have sufficient time to properly analyze these cases, we will defer to
    // WebCore. We only check that the parent is not aria because we do not expect
    // anonymous blocks which are aria-related to themselves have an aria role, nor
    // have we encountered instances where the parent of an anonymous block also lacked
    // an aria role but the grandparent had one.
    if (renderer() && renderer()->isAnonymousBlock() && !parent->renderer()->isBody()
        && parent->ariaRoleAttribute() == UnknownRole)
        return IgnoreObject;

    return DefaultBehavior;
}

AccessibilityObjectWrapper* AccessibilityObject::wrapper() const
{
    return m_wrapper;
}

void AccessibilityObject::setWrapper(AccessibilityObjectWrapper* wrapper)
{
    if (wrapper == m_wrapper)
        return;

    if (m_wrapper)
        g_object_unref(m_wrapper);

    m_wrapper = wrapper;

    if (m_wrapper)
        g_object_ref(m_wrapper);
}

bool AccessibilityObject::allowsTextRanges() const
{
    // Check type for the AccessibilityObject.
    if (isTextControl() || isWebArea() || isGroup() || isLink() || isHeading() || isListItem() || isTableCell())
        return true;

    // Check roles as the last fallback mechanism.
    AccessibilityRole role = roleValue();
    return role == ParagraphRole || role == LabelRole || role == DivRole || role == FormRole;
}

unsigned AccessibilityObject::getLengthForTextRange() const
{
    unsigned textLength = text().length();

    if (textLength)
        return textLength;

    // Gtk ATs need this for all text objects; not just text controls.
    Node* node = this->node();
    RenderObject* renderer = node ? node->renderer() : 0;
    if (renderer && renderer->isText()) {
        RenderText* renderText = toRenderText(renderer);
        textLength = renderText ? renderText->textLength() : 0;
    }

    // Get the text length from the elements under the
    // accessibility object if the value is still zero.
    if (!textLength && allowsTextRanges())
        textLength = textUnderElement().length();

    return textLength;
}

} // namespace WebCore

#endif // HAVE(ACCESSIBILITY)