AX: Notification should be sent when accessibilityIsIgnored changes
[WebKit-https.git] / Source / WebCore / accessibility / AXObjectCache.h
1 /*
2  * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef AXObjectCache_h
27 #define AXObjectCache_h
28
29 #include "AccessibilityObject.h"
30 #include "Timer.h"
31 #include <limits.h>
32 #include <wtf/Forward.h>
33 #include <wtf/HashMap.h>
34 #include <wtf/HashSet.h>
35 #include <wtf/RefPtr.h>
36
37 namespace WebCore {
38
39 class Document;
40 class HTMLAreaElement;
41 class Node;
42 class Page;
43 class RenderObject;
44 class ScrollView;
45 class VisiblePosition;
46 class Widget;
47
48 struct TextMarkerData {
49     AXID axID;
50     Node* node;
51     int offset;
52     EAffinity affinity;
53 };
54
55 enum PostType { PostSynchronously, PostAsynchronously };
56
57 class AXObjectCache {
58     WTF_MAKE_NONCOPYABLE(AXObjectCache); WTF_MAKE_FAST_ALLOCATED;
59 public:
60     explicit AXObjectCache(const Document*);
61     ~AXObjectCache();
62
63     static AccessibilityObject* focusedUIElementForPage(const Page*);
64
65     // Returns the root object for the entire document.
66     AccessibilityObject* rootObject();
67     // Returns the root object for a specific frame.
68     AccessibilityObject* rootObjectForFrame(Frame*);
69     
70     // For AX objects with elements that back them.
71     AccessibilityObject* getOrCreate(RenderObject*);
72     AccessibilityObject* getOrCreate(Widget*);
73     AccessibilityObject* getOrCreate(Node*);
74
75     // used for objects without backing elements
76     AccessibilityObject* getOrCreate(AccessibilityRole);
77     
78     // will only return the AccessibilityObject if it already exists
79     AccessibilityObject* get(RenderObject*);
80     AccessibilityObject* get(Widget*);
81     AccessibilityObject* get(Node*);
82     
83     void remove(RenderObject*);
84     void remove(Node*);
85     void remove(Widget*);
86     void remove(AXID);
87
88     void detachWrapper(AccessibilityObject*);
89     void attachWrapper(AccessibilityObject*);
90     void childrenChanged(Node*);
91     void childrenChanged(RenderObject*);
92     void childrenChanged(AccessibilityObject*);
93     void checkedStateChanged(Node*);
94     void selectedChildrenChanged(Node*);
95     void selectedChildrenChanged(RenderObject*);
96     // Called by a node when text or a text equivalent (e.g. alt) attribute is changed.
97     void textChanged(Node*);
98     void textChanged(RenderObject*);
99     // Called when a node has just been attached, so we can make sure we have the right subclass of AccessibilityObject.
100     void updateCacheAfterNodeIsAttached(Node*);
101
102     void handleActiveDescendantChanged(Node*);
103     void handleAriaRoleChanged(Node*);
104     void handleFocusedUIElementChanged(Node* oldFocusedNode, Node* newFocusedNode);
105     void handleScrolledToAnchor(const Node* anchorNode);
106     void handleAriaExpandedChange(Node*);
107     void handleScrollbarUpdate(ScrollView*);
108
109     void handleAttributeChanged(const QualifiedName& attrName, Element*);
110     void recomputeIsIgnored(RenderObject* renderer);
111
112 #if HAVE(ACCESSIBILITY)
113     static void enableAccessibility() { gAccessibilityEnabled = true; }
114     // Enhanced user interface accessibility can be toggled by the assistive technology.
115     static void setEnhancedUserInterfaceAccessibility(bool flag) { gAccessibilityEnhancedUserInterfaceEnabled = flag; }
116     
117     static bool accessibilityEnabled() { return gAccessibilityEnabled; }
118     static bool accessibilityEnhancedUserInterfaceEnabled() { return gAccessibilityEnhancedUserInterfaceEnabled; }
119 #else
120     static void enableAccessibility() { }
121     static void setEnhancedUserInterfaceAccessibility(bool) { }
122     static bool accessibilityEnabled() { return false; }
123     static bool accessibilityEnhancedUserInterfaceEnabled() { return false; }
124 #endif
125
126     void removeAXID(AccessibilityObject*);
127     bool isIDinUse(AXID id) const { return m_idsInUse.contains(id); }
128
129     Element* rootAXEditableElement(Node*);
130     const Element* rootAXEditableElement(const Node*);
131     bool nodeIsTextControl(const Node*);
132
133     AXID platformGenerateAXID() const;
134     AccessibilityObject* objectFromAXID(AXID id) const { return m_objects.get(id).get(); }
135
136     // Text marker utilities.
137     void textMarkerDataForVisiblePosition(TextMarkerData&, const VisiblePosition&);
138     VisiblePosition visiblePositionForTextMarkerData(TextMarkerData&);
139
140     enum AXNotification {
141         AXActiveDescendantChanged,
142         AXAutocorrectionOccured,
143         AXCheckedStateChanged,
144         AXChildrenChanged,
145         AXFocusedUIElementChanged,
146         AXLayoutComplete,
147         AXLoadComplete,
148         AXSelectedChildrenChanged,
149         AXSelectedTextChanged,
150         AXValueChanged,
151         AXScrolledToAnchor,
152         AXLiveRegionChanged,
153         AXMenuListItemSelected,
154         AXMenuListValueChanged,
155         AXRowCountChanged,
156         AXRowCollapsed,
157         AXRowExpanded,
158         AXInvalidStatusChanged,
159         AXTextChanged,
160         AXAriaAttributeChanged
161     };
162
163     void postNotification(RenderObject*, AXNotification, bool postToElement, PostType = PostAsynchronously);
164     void postNotification(Node*, AXNotification, bool postToElement, PostType = PostAsynchronously);
165     void postNotification(AccessibilityObject*, Document*, AXNotification, bool postToElement, PostType = PostAsynchronously);
166
167     enum AXTextChange {
168         AXTextInserted,
169         AXTextDeleted,
170     };
171
172     void nodeTextChangeNotification(Node*, AXTextChange, unsigned offset, const String&);
173
174     enum AXLoadingEvent {
175         AXLoadingStarted,
176         AXLoadingReloaded,
177         AXLoadingFailed,
178         AXLoadingFinished
179     };
180
181     void frameLoadingEventNotification(Frame*, AXLoadingEvent);
182
183     bool nodeHasRole(Node*, const AtomicString& role);
184
185 protected:
186     void postPlatformNotification(AccessibilityObject*, AXNotification);
187     void nodeTextChangePlatformNotification(AccessibilityObject*, AXTextChange, unsigned offset, const String&);
188     void frameLoadingEventPlatformNotification(AccessibilityObject*, AXLoadingEvent);
189     void textChanged(AccessibilityObject*);
190     void labelChanged(Element*);
191
192     // This is a weak reference cache for knowing if Nodes used by TextMarkers are valid.
193     void setNodeInUse(Node* n) { m_textMarkerNodes.add(n); }
194     void removeNodeForUse(Node* n) { m_textMarkerNodes.remove(n); }
195     bool isNodeInUse(Node* n) { return m_textMarkerNodes.contains(n); }
196
197 private:
198     Document* m_document;
199     HashMap<AXID, RefPtr<AccessibilityObject> > m_objects;
200     HashMap<RenderObject*, AXID> m_renderObjectMapping;
201     HashMap<Widget*, AXID> m_widgetObjectMapping;
202     HashMap<Node*, AXID> m_nodeObjectMapping;
203     HashSet<Node*> m_textMarkerNodes;
204     static bool gAccessibilityEnabled;
205     static bool gAccessibilityEnhancedUserInterfaceEnabled;
206     
207     HashSet<AXID> m_idsInUse;
208     
209     Timer<AXObjectCache> m_notificationPostTimer;
210     Vector<pair<RefPtr<AccessibilityObject>, AXNotification> > m_notificationsToPost;
211     void notificationPostTimerFired(Timer<AXObjectCache>*);
212     
213     static AccessibilityObject* focusedImageMapUIElement(HTMLAreaElement*);
214     
215     AXID getAXID(AccessibilityObject*);
216 };
217
218 bool nodeHasRole(Node*, const String& role);
219 // This will let you know if aria-hidden was explicitly set to false.
220 bool isNodeAriaVisible(Node*);
221     
222 #if !HAVE(ACCESSIBILITY)
223 inline AXObjectCache::AXObjectCache(const Document* doc) : m_document(const_cast<Document*>(doc)), m_notificationPostTimer(this, 0) { }
224 inline AXObjectCache::~AXObjectCache() { }
225 inline AccessibilityObject* AXObjectCache::focusedUIElementForPage(const Page*) { return 0; }
226 inline AccessibilityObject* AXObjectCache::get(RenderObject*) { return 0; }
227 inline AccessibilityObject* AXObjectCache::get(Node*) { return 0; }
228 inline AccessibilityObject* AXObjectCache::get(Widget*) { return 0; }
229 inline AccessibilityObject* AXObjectCache::getOrCreate(AccessibilityRole) { return 0; }
230 inline AccessibilityObject* AXObjectCache::getOrCreate(RenderObject*) { return 0; }
231 inline AccessibilityObject* AXObjectCache::getOrCreate(Node*) { return 0; }
232 inline AccessibilityObject* AXObjectCache::getOrCreate(Widget*) { return 0; }
233 inline AccessibilityObject* AXObjectCache::rootObject() { return 0; }
234 inline AccessibilityObject* AXObjectCache::rootObjectForFrame(Frame*) { return 0; }
235 inline Element* AXObjectCache::rootAXEditableElement(Node*) { return 0; }
236 inline bool nodeHasRole(Node*, const String&) { return false; }
237 inline bool isNodeAriaVisible(Node*) { return true; }
238 inline const Element* AXObjectCache::rootAXEditableElement(const Node*) { return 0; }
239 inline void AXObjectCache::attachWrapper(AccessibilityObject*) { }
240 inline void AXObjectCache::checkedStateChanged(Node*) { }
241 inline void AXObjectCache::childrenChanged(RenderObject*) { }
242 inline void AXObjectCache::childrenChanged(Node*) { }
243 inline void AXObjectCache::childrenChanged(AccessibilityObject*) { }
244 inline void AXObjectCache::textChanged(RenderObject*) { }
245 inline void AXObjectCache::textChanged(Node*) { }
246 inline void AXObjectCache::textChanged(AccessibilityObject*) { }
247 inline void AXObjectCache::updateCacheAfterNodeIsAttached(Node*) { }
248 inline void AXObjectCache::detachWrapper(AccessibilityObject*) { }
249 inline void AXObjectCache::frameLoadingEventNotification(Frame*, AXLoadingEvent) { }
250 inline void AXObjectCache::frameLoadingEventPlatformNotification(AccessibilityObject*, AXLoadingEvent) { }
251 inline void AXObjectCache::handleActiveDescendantChanged(Node*) { }
252 inline void AXObjectCache::handleAriaExpandedChange(Node*) { }
253 inline void AXObjectCache::handleAriaRoleChanged(Node*) { }
254 inline void AXObjectCache::handleFocusedUIElementChanged(Node*, Node*) { }
255 inline void AXObjectCache::handleScrollbarUpdate(ScrollView*) { }
256 inline void AXObjectCache::handleAttributeChanged(const QualifiedName&, Element*) { }
257 inline void AXObjectCache::recomputeIsIgnored(RenderObject*) { }
258 inline void AXObjectCache::handleScrolledToAnchor(const Node*) { }
259 inline void AXObjectCache::nodeTextChangeNotification(Node*, AXTextChange, unsigned, const String&) { }
260 inline void AXObjectCache::nodeTextChangePlatformNotification(AccessibilityObject*, AXTextChange, unsigned, const String&) { }
261 inline void AXObjectCache::postNotification(AccessibilityObject*, Document*, AXNotification, bool, PostType) { }
262 inline void AXObjectCache::postNotification(RenderObject*, AXNotification, bool, PostType) { }
263 inline void AXObjectCache::postNotification(Node*, AXNotification, bool, PostType) { }
264 inline void AXObjectCache::postPlatformNotification(AccessibilityObject*, AXNotification) { }
265 inline void AXObjectCache::remove(AXID) { }
266 inline void AXObjectCache::remove(RenderObject*) { }
267 inline void AXObjectCache::remove(Node*) { }
268 inline void AXObjectCache::remove(Widget*) { }
269 inline void AXObjectCache::selectedChildrenChanged(RenderObject*) { }
270 inline void AXObjectCache::selectedChildrenChanged(Node*) { }
271 #endif
272
273 }
274
275 #endif