1 /* 2 * Copyright (C) 2008, 2009, 2010 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 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 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 27 #include "config.h" 28 #include "AXObjectCache.h" 29 30 #include "AccessibilityObject.h" 31 #include "Chrome.h" 32 #include "Document.h" 33 #include "Page.h" 34 #include "RenderObject.h" 35 36 using namespace std; 37 38 namespace WebCore { 39 40 void AXObjectCache::detachWrapper(AccessibilityObject* obj) 41 { 42 // On Windows, AccessibilityObjects are created when get_accChildCount is 43 // called, but they are not wrapped until get_accChild is called, so this 44 // object may not have a wrapper. 45 if (AccessibilityObjectWrapper* wrapper = obj->wrapper()) 46 wrapper->detach(); 47 } 48 49 void AXObjectCache::attachWrapper(AccessibilityObject*) 50 { 51 // On Windows, AccessibilityObjects are wrapped when the accessibility 52 // software requests them via get_accChild. 53 } 54 55 void AXObjectCache::handleScrolledToAnchor(const Node* anchorNode) 56 { 57 // The anchor node may not be accessible. Post the notification for the 58 // first accessible object. 59 postPlatformNotification(AccessibilityObject::firstAccessibleObjectFromNode(anchorNode), AXScrolledToAnchor); 60 } 61 62 void AXObjectCache::postPlatformNotification(AccessibilityObject* obj, AXNotification notification) 63 { 64 if (!obj) 65 return; 66 67 Document* document = obj->document(); 68 if (!document) 69 return; 70 71 Page* page = document->page(); 72 if (!page || !page->chrome()->platformPageClient()) 73 return; 74 75 DWORD msaaEvent; 76 switch (notification) { 77 case AXFocusedUIElementChanged: 78 case AXActiveDescendantChanged: 79 msaaEvent = EVENT_OBJECT_FOCUS; 80 break; 81 82 case AXScrolledToAnchor: 83 msaaEvent = EVENT_SYSTEM_SCROLLINGSTART; 84 break; 85 86 case AXValueChanged: 87 case AXMenuListValueChanged: 88 msaaEvent = EVENT_OBJECT_VALUECHANGE; 89 break; 90 91 default: 92 return; 93 } 94 95 // Windows will end up calling get_accChild() on the root accessible 96 // object for the WebView, passing the child ID that we specify below. We 97 // negate the AXID so we know that the caller is passing the ID of an 98 // element, not the index of a child element. 99 100 ASSERT(obj->axObjectID() >= 1); 101 ASSERT(obj->axObjectID() <= numeric_limits<LONG>::max()); 102 103 NotifyWinEvent(msaaEvent, page->chrome()->platformPageClient(), OBJID_CLIENT, -static_cast<LONG>(obj->axObjectID())); 104 } 105 106 AXID AXObjectCache::platformGenerateAXID() const 107 { 108 static AXID lastUsedID = 0; 109 110 // Generate a new ID. Windows accessibility relies on a positive AXID, 111 // ranging from 1 to LONG_MAX. 112 AXID objID = lastUsedID; 113 do { 114 ++objID; 115 objID %= std::numeric_limits<LONG>::max(); 116 } while (objID == 0 || HashTraits<AXID>::isDeletedValue(objID) || m_idsInUse.contains(objID)); 117 118 ASSERT(objID >= 1 && objID <= std::numeric_limits<LONG>::max()); 119 120 lastUsedID = objID; 121 122 return objID; 123 } 124 125 void AXObjectCache::handleFocusedUIElementChanged(RenderObject*, RenderObject* newFocusedRenderer) 126 { 127 if (!newFocusedRenderer) 128 return; 129 130 Page* page = newFocusedRenderer->document()->page(); 131 if (!page || !page->chrome()->platformPageClient()) 132 return; 133 134 AccessibilityObject* focusedObject = focusedUIElementForPage(page); 135 if (!focusedObject) 136 return; 137 138 ASSERT(!focusedObject->accessibilityIsIgnored()); 139 140 postPlatformNotification(focusedObject, AXFocusedUIElementChanged); 141 } 142 143 } // namespace WebCore 144