546f38191fac4d35a0d0c76d4aab9d4ab4e683e6
[WebKit-https.git] / Source / WebCore / accessibility / win / AXObjectCacheWin.cpp
1 /*
2  * Copyright (C) 2008, 2009, 2010, 2013 Apple Inc. All Rights Reserved.
3  * Copyright (C) 2012 Serotek Corporation. All Rights Reserved.
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
28 #include "config.h"
29 #include "AXObjectCache.h"
30
31 #include "AccessibilityObject.h"
32 #include "Chrome.h"
33 #include "ChromeClient.h"
34 #include "Document.h"
35 #include "Page.h"
36 #include "RenderObject.h"
37
38 // Provided by IAccessibleEventID.idl
39 #define IA2_EVENT_DOCUMENT_LOAD_COMPLETE    261
40
41
42 namespace WebCore {
43
44 void AXObjectCache::detachWrapper(AccessibilityObject* obj, AccessibilityDetachmentType)
45 {
46     // On Windows, AccessibilityObjects are created when get_accChildCount is
47     // called, but they are not wrapped until get_accChild is called, so this
48     // object may not have a wrapper.
49     if (AccessibilityObjectWrapper* wrapper = obj->wrapper())
50         wrapper->detach();
51 }
52
53 void AXObjectCache::attachWrapper(AccessibilityObject*)
54 {
55     // On Windows, AccessibilityObjects are wrapped when the accessibility
56     // software requests them via get_accChild.
57 }
58
59 void AXObjectCache::handleScrolledToAnchor(const Node* anchorNode)
60 {
61     // The anchor node may not be accessible. Post the notification for the
62     // first accessible object.
63     postPlatformNotification(AccessibilityObject::firstAccessibleObjectFromNode(anchorNode), AXScrolledToAnchor);
64 }
65
66 void AXObjectCache::postPlatformNotification(AccessibilityObject* obj, AXNotification notification)
67 {
68     if (!obj)
69         return;
70
71     Document* document = obj->document();
72     if (!document)
73         return;
74
75     Page* page = document->page();
76     if (!page || !page->chrome().platformPageClient())
77         return;
78
79     DWORD msaaEvent;
80     switch (notification) {
81         case AXCheckedStateChanged:
82             msaaEvent = EVENT_OBJECT_STATECHANGE;
83             break;
84
85         case AXFocusedUIElementChanged:
86         case AXActiveDescendantChanged:
87             msaaEvent = EVENT_OBJECT_FOCUS;
88             break;
89
90         case AXScrolledToAnchor:
91             msaaEvent = EVENT_SYSTEM_SCROLLINGSTART;
92             break;
93
94         case AXLayoutComplete:
95             msaaEvent = EVENT_OBJECT_REORDER;
96             break;
97
98         case AXLoadComplete:
99             msaaEvent = IA2_EVENT_DOCUMENT_LOAD_COMPLETE;
100             break;
101
102         case AXValueChanged:
103         case AXMenuListValueChanged:
104             msaaEvent = EVENT_OBJECT_VALUECHANGE;
105             break;
106
107         case AXMenuListItemSelected:
108             msaaEvent = EVENT_OBJECT_SELECTION;
109             break;
110
111         default:
112             return;
113     }
114
115     // Windows will end up calling get_accChild() on the root accessible
116     // object for the WebView, passing the child ID that we specify below. We
117     // negate the AXID so we know that the caller is passing the ID of an
118     // element, not the index of a child element.
119
120     ASSERT(obj->axObjectID() >= 1);
121     ASSERT(obj->axObjectID() <= std::numeric_limits<LONG>::max());
122
123     NotifyWinEvent(msaaEvent, page->chrome().platformPageClient(), OBJID_CLIENT, -static_cast<LONG>(obj->axObjectID()));
124 }
125
126 void AXObjectCache::nodeTextChangePlatformNotification(AccessibilityObject*, AXTextChange, unsigned, const String&)
127 {
128 }
129
130 void AXObjectCache::frameLoadingEventPlatformNotification(AccessibilityObject* obj, AXLoadingEvent notification)
131 {
132     if (!obj)
133         return;
134     
135     Document* document = obj->document();
136     if (!document)
137         return;
138
139     Page* page = document->page();
140     if (!page)
141         return;
142
143     if (notification == AXLoadingStarted)
144         page->chrome().client().AXStartFrameLoad();
145     else if (notification == AXLoadingFinished)
146         page->chrome().client().AXFinishFrameLoad();
147 }
148
149 AXID AXObjectCache::platformGenerateAXID() const
150 {
151     static AXID lastUsedID = 0;
152
153     // Generate a new ID. Windows accessibility relies on a positive AXID,
154     // ranging from 1 to LONG_MAX.
155     AXID objID = lastUsedID;
156     do {
157         ++objID;
158         objID %= std::numeric_limits<LONG>::max();
159     } while (objID == 0 || HashTraits<AXID>::isDeletedValue(objID) || m_idsInUse.contains(objID));
160
161     ASSERT(objID >= 1 && objID <= std::numeric_limits<LONG>::max());
162
163     lastUsedID = objID;
164
165     return objID;
166 }
167
168 void AXObjectCache::platformHandleFocusedUIElementChanged(Node*, Node* newFocusedNode)
169 {
170     if (!newFocusedNode)
171         return;
172
173     Page* page = newFocusedNode->document().page();
174     if (!page || !page->chrome().platformPageClient())
175         return;
176
177     AccessibilityObject* focusedObject = focusedUIElementForPage(page);
178     if (!focusedObject)
179         return;
180
181     ASSERT(!focusedObject->accessibilityIsIgnored());
182
183     postPlatformNotification(focusedObject, AXFocusedUIElementChanged);
184 }
185
186 } // namespace WebCore