18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
2d0825bca7fe65beaee391d30da42e937db621564Steve Block * Copyright (C) 2008, 2009, 2010 Apple Inc. All Rights Reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "AXObjectCache.h"
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "AccessibilityObject.h"
31d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "Chrome.h"
32231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "Document.h"
33231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "Page.h"
34231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "RenderObject.h"
35231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
36231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockusing namespace std;
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid AXObjectCache::detachWrapper(AccessibilityObject* obj)
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // On Windows, AccessibilityObjects are created when get_accChildCount is
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // called, but they are not wrapped until get_accChild is called, so this
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // object may not have a wrapper.
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (AccessibilityObjectWrapper* wrapper = obj->wrapper())
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        wrapper->detach();
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid AXObjectCache::attachWrapper(AccessibilityObject*)
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // On Windows, AccessibilityObjects are wrapped when the accessibility
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // software requests them via get_accChild.
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
55231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid AXObjectCache::handleScrolledToAnchor(const Node* anchorNode)
56231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
57231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // The anchor node may not be accessible. Post the notification for the
58231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // first accessible object.
59231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    postPlatformNotification(AccessibilityObject::firstAccessibleObjectFromNode(anchorNode), AXScrolledToAnchor);
60231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
61231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
62231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid AXObjectCache::postPlatformNotification(AccessibilityObject* obj, AXNotification notification)
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
64231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!obj)
65231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
66231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
67231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    Document* document = obj->document();
68231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!document)
69231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
70231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
71231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    Page* page = document->page();
72231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!page || !page->chrome()->platformPageClient())
73231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
74231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
75231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    DWORD msaaEvent;
76231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    switch (notification) {
77231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        case AXFocusedUIElementChanged:
78643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        case AXActiveDescendantChanged:
79231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            msaaEvent = EVENT_OBJECT_FOCUS;
80231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            break;
81231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
82231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        case AXScrolledToAnchor:
83231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            msaaEvent = EVENT_SYSTEM_SCROLLINGSTART;
84231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            break;
85231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
86d0825bca7fe65beaee391d30da42e937db621564Steve Block        case AXValueChanged:
87d0825bca7fe65beaee391d30da42e937db621564Steve Block        case AXMenuListValueChanged:
88d0825bca7fe65beaee391d30da42e937db621564Steve Block            msaaEvent = EVENT_OBJECT_VALUECHANGE;
89d0825bca7fe65beaee391d30da42e937db621564Steve Block            break;
90d0825bca7fe65beaee391d30da42e937db621564Steve Block
91231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        default:
92231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return;
93231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
94231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
95231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Windows will end up calling get_accChild() on the root accessible
96231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // object for the WebView, passing the child ID that we specify below. We
97231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // negate the AXID so we know that the caller is passing the ID of an
98231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // element, not the index of a child element.
99231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
100231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ASSERT(obj->axObjectID() >= 1);
101231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ASSERT(obj->axObjectID() <= numeric_limits<LONG>::max());
102231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
103231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    NotifyWinEvent(msaaEvent, page->chrome()->platformPageClient(), OBJID_CLIENT, -static_cast<LONG>(obj->axObjectID()));
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
106bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AXObjectCache::nodeTextChangePlatformNotification(AccessibilityObject*, AXTextChange, unsigned, unsigned)
107bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
108bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
109bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
110231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockAXID AXObjectCache::platformGenerateAXID() const
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
112231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    static AXID lastUsedID = 0;
113231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
114231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Generate a new ID. Windows accessibility relies on a positive AXID,
115231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // ranging from 1 to LONG_MAX.
116231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    AXID objID = lastUsedID;
117231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    do {
118231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ++objID;
119231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        objID %= std::numeric_limits<LONG>::max();
120231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    } while (objID == 0 || HashTraits<AXID>::isDeletedValue(objID) || m_idsInUse.contains(objID));
121231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
122231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ASSERT(objID >= 1 && objID <= std::numeric_limits<LONG>::max());
123231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
124231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    lastUsedID = objID;
125231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
126231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return objID;
127231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
128231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
129231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid AXObjectCache::handleFocusedUIElementChanged(RenderObject*, RenderObject* newFocusedRenderer)
130231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
131231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!newFocusedRenderer)
132231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
133231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
134231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    Page* page = newFocusedRenderer->document()->page();
135231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!page || !page->chrome()->platformPageClient())
136231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
137231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
138231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    AccessibilityObject* focusedObject = focusedUIElementForPage(page);
139231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!focusedObject)
140231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
141231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
142231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ASSERT(!focusedObject->accessibilityIsIgnored());
143231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
144231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    postPlatformNotification(focusedObject, AXFocusedUIElementChanged);
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore
148