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 void AXObjectCache::nodeTextChangePlatformNotification(AccessibilityObject*, AXTextChange, unsigned, unsigned) 107 { 108 } 109 110 AXID AXObjectCache::platformGenerateAXID() const 111 { 112 static AXID lastUsedID = 0; 113 114 // Generate a new ID. Windows accessibility relies on a positive AXID, 115 // ranging from 1 to LONG_MAX. 116 AXID objID = lastUsedID; 117 do { 118 ++objID; 119 objID %= std::numeric_limits<LONG>::max(); 120 } while (objID == 0 || HashTraits<AXID>::isDeletedValue(objID) || m_idsInUse.contains(objID)); 121 122 ASSERT(objID >= 1 && objID <= std::numeric_limits<LONG>::max()); 123 124 lastUsedID = objID; 125 126 return objID; 127 } 128 129 void AXObjectCache::handleFocusedUIElementChanged(RenderObject*, RenderObject* newFocusedRenderer) 130 { 131 if (!newFocusedRenderer) 132 return; 133 134 Page* page = newFocusedRenderer->document()->page(); 135 if (!page || !page->chrome()->platformPageClient()) 136 return; 137 138 AccessibilityObject* focusedObject = focusedUIElementForPage(page); 139 if (!focusedObject) 140 return; 141 142 ASSERT(!focusedObject->accessibilityIsIgnored()); 143 144 postPlatformNotification(focusedObject, AXFocusedUIElementChanged); 145 } 146 147 } // namespace WebCore 148