diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-01-06 14:44:00 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-01-06 14:44:00 +0100 |
commit | 40736c5763bf61337c8c14e16d8587db021a87d4 (patch) | |
tree | b17a9c00042ad89cb1308e2484491799aa14e9f8 /Source/WebKit/win/AccessibleBase.cpp | |
download | qtwebkit-40736c5763bf61337c8c14e16d8587db021a87d4.tar.gz |
Imported WebKit commit 2ea9d364d0f6efa8fa64acf19f451504c59be0e4 (http://svn.webkit.org/repository/webkit/trunk@104285)
Diffstat (limited to 'Source/WebKit/win/AccessibleBase.cpp')
-rw-r--r-- | Source/WebKit/win/AccessibleBase.cpp | 727 |
1 files changed, 727 insertions, 0 deletions
diff --git a/Source/WebKit/win/AccessibleBase.cpp b/Source/WebKit/win/AccessibleBase.cpp new file mode 100644 index 000000000..d26086677 --- /dev/null +++ b/Source/WebKit/win/AccessibleBase.cpp @@ -0,0 +1,727 @@ +/* + * Copyright (C) 2008, 2009, 2010 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebKitDLL.h" +#include "AccessibleBase.h" + +#include "AccessibleImage.h" +#include "WebView.h" +#include <WebCore/AccessibilityListBox.h> +#include <WebCore/AccessibilityMenuListPopup.h> +#include <WebCore/AccessibilityObject.h> +#include <WebCore/AXObjectCache.h> +#include <WebCore/BString.h> +#include <WebCore/Element.h> +#include <WebCore/EventHandler.h> +#include <WebCore/FrameView.h> +#include <WebCore/HostWindow.h> +#include <WebCore/HTMLNames.h> +#include <WebCore/HTMLFrameElementBase.h> +#include <WebCore/HTMLInputElement.h> +#include <WebCore/IntRect.h> +#include <WebCore/PlatformEvent.h> +#include <WebCore/RenderFrame.h> +#include <WebCore/RenderObject.h> +#include <WebCore/RenderView.h> +#include <oleacc.h> +#include <wtf/RefPtr.h> + +using namespace WebCore; + +AccessibleBase::AccessibleBase(AccessibilityObject* obj) + : AccessibilityObjectWrapper(obj) + , m_refCount(0) +{ + ASSERT_ARG(obj, obj); + m_object->setWrapper(this); + ++gClassCount; + gClassNameCount.add("AccessibleBase"); +} + +AccessibleBase::~AccessibleBase() +{ + --gClassCount; + gClassNameCount.remove("AccessibleBase"); +} + +AccessibleBase* AccessibleBase::createInstance(AccessibilityObject* obj) +{ + ASSERT_ARG(obj, obj); + + if (obj->isImage()) + return new AccessibleImage(obj); + + return new AccessibleBase(obj); +} + +HRESULT AccessibleBase::QueryService(REFGUID guidService, REFIID riid, void **ppvObject) +{ + if (!IsEqualGUID(guidService, SID_AccessibleComparable)) { + *ppvObject = 0; + return E_INVALIDARG; + } + return QueryInterface(riid, ppvObject); +} + +// IUnknown +HRESULT STDMETHODCALLTYPE AccessibleBase::QueryInterface(REFIID riid, void** ppvObject) +{ + if (IsEqualGUID(riid, __uuidof(IAccessible))) + *ppvObject = static_cast<IAccessible*>(this); + else if (IsEqualGUID(riid, __uuidof(IDispatch))) + *ppvObject = static_cast<IAccessible*>(this); + else if (IsEqualGUID(riid, __uuidof(IUnknown))) + *ppvObject = static_cast<IAccessible*>(this); + else if (IsEqualGUID(riid, __uuidof(IAccessibleComparable))) + *ppvObject = static_cast<IAccessibleComparable*>(this); + else if (IsEqualGUID(riid, __uuidof(IServiceProvider))) + *ppvObject = static_cast<IServiceProvider*>(this); + else if (IsEqualGUID(riid, __uuidof(AccessibleBase))) + *ppvObject = static_cast<AccessibleBase*>(this); + else { + *ppvObject = 0; + return E_NOINTERFACE; + } + AddRef(); + return S_OK; +} + +ULONG STDMETHODCALLTYPE AccessibleBase::Release(void) +{ + ASSERT(m_refCount > 0); + if (--m_refCount) + return m_refCount; + delete this; + return 0; +} + +// IAccessible +HRESULT STDMETHODCALLTYPE AccessibleBase::get_accParent(IDispatch** parent) +{ + *parent = 0; + + if (!m_object) + return E_FAIL; + + AccessibilityObject* parentObject = m_object->parentObjectUnignored(); + if (parentObject) { + *parent = wrapper(parentObject); + (*parent)->AddRef(); + return S_OK; + } + + if (!m_object->topDocumentFrameView()) + return E_FAIL; + + return WebView::AccessibleObjectFromWindow(m_object->topDocumentFrameView()->hostWindow()->platformPageClient(), + OBJID_WINDOW, __uuidof(IAccessible), reinterpret_cast<void**>(parent)); +} + +HRESULT STDMETHODCALLTYPE AccessibleBase::get_accChildCount(long* count) +{ + if (!m_object) + return E_FAIL; + if (!count) + return E_POINTER; + *count = static_cast<long>(m_object->children().size()); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE AccessibleBase::get_accChild(VARIANT vChild, IDispatch** ppChild) +{ + if (!ppChild) + return E_POINTER; + + *ppChild = 0; + + AccessibilityObject* childObj; + + HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); + if (FAILED(hr)) + return hr; + + *ppChild = static_cast<IDispatch*>(wrapper(childObj)); + (*ppChild)->AddRef(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE AccessibleBase::get_accName(VARIANT vChild, BSTR* name) +{ + if (!name) + return E_POINTER; + + *name = 0; + + AccessibilityObject* childObj; + HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); + + if (FAILED(hr)) + return hr; + + if (*name = BString(wrapper(childObj)->name()).release()) + return S_OK; + return S_FALSE; +} + +HRESULT STDMETHODCALLTYPE AccessibleBase::get_accValue(VARIANT vChild, BSTR* value) +{ + if (!value) + return E_POINTER; + + *value = 0; + + AccessibilityObject* childObj; + HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); + + if (FAILED(hr)) + return hr; + + if (*value = BString(wrapper(childObj)->value()).release()) + return S_OK; + return S_FALSE; +} + +HRESULT STDMETHODCALLTYPE AccessibleBase::get_accDescription(VARIANT vChild, BSTR* description) +{ + if (!description) + return E_POINTER; + + *description = 0; + + AccessibilityObject* childObj; + HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); + + if (FAILED(hr)) + return hr; + + if (*description = BString(childObj->descriptionForMSAA()).release()) + return S_OK; + + return S_FALSE; +} + +HRESULT STDMETHODCALLTYPE AccessibleBase::get_accRole(VARIANT vChild, VARIANT* pvRole) +{ + if (!pvRole) + return E_POINTER; + + ::VariantInit(pvRole); + + AccessibilityObject* childObj; + HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); + + if (FAILED(hr)) + return hr; + + String roleString = childObj->stringRoleForMSAA(); + if (!roleString.isEmpty()) { + V_VT(pvRole) = VT_BSTR; + V_BSTR(pvRole) = BString(roleString).release(); + return S_OK; + } + + pvRole->vt = VT_I4; + pvRole->lVal = wrapper(childObj)->role(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE AccessibleBase::get_accState(VARIANT vChild, VARIANT* pvState) +{ + if (!pvState) + return E_POINTER; + + ::VariantInit(pvState); + + AccessibilityObject* childObj; + HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); + + if (FAILED(hr)) + return hr; + + pvState->vt = VT_I4; + pvState->lVal = 0; + + if (childObj->isLinked()) + pvState->lVal |= STATE_SYSTEM_LINKED; + + if (childObj->isHovered()) + pvState->lVal |= STATE_SYSTEM_HOTTRACKED; + + if (!childObj->isEnabled()) + pvState->lVal |= STATE_SYSTEM_UNAVAILABLE; + + if (childObj->isReadOnly()) + pvState->lVal |= STATE_SYSTEM_READONLY; + + if (childObj->isOffScreen()) + pvState->lVal |= STATE_SYSTEM_OFFSCREEN; + + if (childObj->isPasswordField()) + pvState->lVal |= STATE_SYSTEM_PROTECTED; + + if (childObj->isIndeterminate()) + pvState->lVal |= STATE_SYSTEM_INDETERMINATE; + + if (childObj->isChecked()) + pvState->lVal |= STATE_SYSTEM_CHECKED; + + if (childObj->isPressed()) + pvState->lVal |= STATE_SYSTEM_PRESSED; + + if (childObj->isFocused()) + pvState->lVal |= STATE_SYSTEM_FOCUSED; + + if (childObj->isVisited()) + pvState->lVal |= STATE_SYSTEM_TRAVERSED; + + if (childObj->canSetFocusAttribute()) + pvState->lVal |= STATE_SYSTEM_FOCUSABLE; + + if (childObj->isSelected()) + pvState->lVal |= STATE_SYSTEM_SELECTED; + + if (childObj->canSetSelectedAttribute()) + pvState->lVal |= STATE_SYSTEM_SELECTABLE; + + if (childObj->isMultiSelectable()) + pvState->lVal |= STATE_SYSTEM_EXTSELECTABLE | STATE_SYSTEM_MULTISELECTABLE; + + if (!childObj->isVisible()) + pvState->lVal |= STATE_SYSTEM_INVISIBLE; + + if (childObj->isCollapsed()) + pvState->lVal |= STATE_SYSTEM_COLLAPSED; + + if (childObj->roleValue() == PopUpButtonRole) { + pvState->lVal |= STATE_SYSTEM_HASPOPUP; + + if (!childObj->isCollapsed()) + pvState->lVal |= STATE_SYSTEM_EXPANDED; + } + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE AccessibleBase::get_accHelp(VARIANT vChild, BSTR* helpText) +{ + if (!helpText) + return E_POINTER; + + *helpText = 0; + + AccessibilityObject* childObj; + HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); + + if (FAILED(hr)) + return hr; + + if (*helpText = BString(childObj->helpText()).release()) + return S_OK; + return S_FALSE; +} + +HRESULT STDMETHODCALLTYPE AccessibleBase::get_accKeyboardShortcut(VARIANT vChild, BSTR* shortcut) +{ + if (!shortcut) + return E_POINTER; + + *shortcut = 0; + + AccessibilityObject* childObj; + HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); + + if (FAILED(hr)) + return hr; + + String accessKey = childObj->accessKey(); + if (accessKey.isNull()) + return S_FALSE; + + static String accessKeyModifiers; + if (accessKeyModifiers.isNull()) { + unsigned modifiers = EventHandler::accessKeyModifiers(); + // Follow the same order as Mozilla MSAA implementation: + // Ctrl+Alt+Shift+Meta+key. MSDN states that keyboard shortcut strings + // should not be localized and defines the separator as "+". + if (modifiers & PlatformEvent::CtrlKey) + accessKeyModifiers += "Ctrl+"; + if (modifiers & PlatformEvent::AltKey) + accessKeyModifiers += "Alt+"; + if (modifiers & PlatformEvent::ShiftKey) + accessKeyModifiers += "Shift+"; + if (modifiers & PlatformEvent::MetaKey) + accessKeyModifiers += "Win+"; + } + *shortcut = BString(String(accessKeyModifiers + accessKey)).release(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE AccessibleBase::accSelect(long selectionFlags, VARIANT vChild) +{ + // According to MSDN, these combinations are invalid. + if (((selectionFlags & (SELFLAG_ADDSELECTION | SELFLAG_REMOVESELECTION)) == (SELFLAG_ADDSELECTION | SELFLAG_REMOVESELECTION)) + || ((selectionFlags & (SELFLAG_ADDSELECTION | SELFLAG_TAKESELECTION)) == (SELFLAG_ADDSELECTION | SELFLAG_TAKESELECTION)) + || ((selectionFlags & (SELFLAG_REMOVESELECTION | SELFLAG_TAKESELECTION)) == (SELFLAG_REMOVESELECTION | SELFLAG_TAKESELECTION)) + || ((selectionFlags & (SELFLAG_EXTENDSELECTION | SELFLAG_TAKESELECTION)) == (SELFLAG_EXTENDSELECTION | SELFLAG_TAKESELECTION))) + return E_INVALIDARG; + + AccessibilityObject* childObject; + HRESULT hr = getAccessibilityObjectForChild(vChild, childObject); + + if (FAILED(hr)) + return hr; + + if (selectionFlags & SELFLAG_TAKEFOCUS) + childObject->setFocused(true); + + AccessibilityObject* parentObject = childObject->parentObject(); + if (!parentObject) + return E_INVALIDARG; + + if (selectionFlags & SELFLAG_TAKESELECTION) { + if (parentObject->isListBox()) { + Vector<RefPtr<AccessibilityObject> > selectedChildren(1); + selectedChildren[0] = childObject; + static_cast<AccessibilityListBox*>(parentObject)->setSelectedChildren(selectedChildren); + } else { // any element may be selectable by virtue of it having the aria-selected property + ASSERT(!parentObject->isMultiSelectable()); + childObject->setSelected(true); + } + } + + // MSDN says that ADD, REMOVE, and EXTENDSELECTION with no other flags are invalid for + // single-select. + const long allSELFLAGs = SELFLAG_TAKEFOCUS | SELFLAG_TAKESELECTION | SELFLAG_EXTENDSELECTION | SELFLAG_ADDSELECTION | SELFLAG_REMOVESELECTION; + if (!parentObject->isMultiSelectable() + && (((selectionFlags & allSELFLAGs) == SELFLAG_ADDSELECTION) + || ((selectionFlags & allSELFLAGs) == SELFLAG_REMOVESELECTION) + || ((selectionFlags & allSELFLAGs) == SELFLAG_EXTENDSELECTION))) + return E_INVALIDARG; + + if (selectionFlags & SELFLAG_ADDSELECTION) + childObject->setSelected(true); + + if (selectionFlags & SELFLAG_REMOVESELECTION) + childObject->setSelected(false); + + // FIXME: Should implement SELFLAG_EXTENDSELECTION. For now, we just return + // S_OK, matching Firefox. + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE AccessibleBase::get_accSelection(VARIANT*) +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE AccessibleBase::get_accFocus(VARIANT* pvFocusedChild) +{ + if (!pvFocusedChild) + return E_POINTER; + + ::VariantInit(pvFocusedChild); + + if (!m_object) + return E_FAIL; + + AccessibilityObject* focusedObj = m_object->focusedUIElement(); + if (!focusedObj) + return S_FALSE; + + if (focusedObj == m_object) { + V_VT(pvFocusedChild) = VT_I4; + V_I4(pvFocusedChild) = CHILDID_SELF; + return S_OK; + } + + V_VT(pvFocusedChild) = VT_DISPATCH; + V_DISPATCH(pvFocusedChild) = wrapper(focusedObj); + V_DISPATCH(pvFocusedChild)->AddRef(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE AccessibleBase::get_accDefaultAction(VARIANT vChild, BSTR* action) +{ + if (!action) + return E_POINTER; + + *action = 0; + + AccessibilityObject* childObj; + HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); + + if (FAILED(hr)) + return hr; + + if (*action = BString(childObj->actionVerb()).release()) + return S_OK; + return S_FALSE; +} + +HRESULT STDMETHODCALLTYPE AccessibleBase::accLocation(long* left, long* top, long* width, long* height, VARIANT vChild) +{ + if (!left || !top || !width || !height) + return E_POINTER; + + *left = *top = *width = *height = 0; + + AccessibilityObject* childObj; + HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); + + if (FAILED(hr)) + return hr; + + if (!childObj->documentFrameView()) + return E_FAIL; + + IntRect screenRect(childObj->documentFrameView()->contentsToScreen(childObj->elementRect())); + *left = screenRect.x(); + *top = screenRect.y(); + *width = screenRect.width(); + *height = screenRect.height(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE AccessibleBase::accNavigate(long direction, VARIANT vFromChild, VARIANT* pvNavigatedTo) +{ + if (!pvNavigatedTo) + return E_POINTER; + + ::VariantInit(pvNavigatedTo); + + AccessibilityObject* childObj = 0; + + switch (direction) { + case NAVDIR_DOWN: + case NAVDIR_UP: + case NAVDIR_LEFT: + case NAVDIR_RIGHT: + // These directions are not implemented, matching Mozilla and IE. + return E_NOTIMPL; + case NAVDIR_LASTCHILD: + case NAVDIR_FIRSTCHILD: + // MSDN states that navigating to first/last child can only be from self. + if (vFromChild.lVal != CHILDID_SELF) + return E_INVALIDARG; + + if (!m_object) + return E_FAIL; + + if (direction == NAVDIR_FIRSTCHILD) + childObj = m_object->firstChild(); + else + childObj = m_object->lastChild(); + break; + case NAVDIR_NEXT: + case NAVDIR_PREVIOUS: { + // Navigating to next and previous is allowed from self or any of our children. + HRESULT hr = getAccessibilityObjectForChild(vFromChild, childObj); + if (FAILED(hr)) + return hr; + + if (direction == NAVDIR_NEXT) + childObj = childObj->nextSibling(); + else + childObj = childObj->previousSibling(); + break; + } + default: + ASSERT_NOT_REACHED(); + return E_INVALIDARG; + } + + if (!childObj) + return S_FALSE; + + V_VT(pvNavigatedTo) = VT_DISPATCH; + V_DISPATCH(pvNavigatedTo) = wrapper(childObj); + V_DISPATCH(pvNavigatedTo)->AddRef(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE AccessibleBase::accHitTest(long x, long y, VARIANT* pvChildAtPoint) +{ + if (!pvChildAtPoint) + return E_POINTER; + + ::VariantInit(pvChildAtPoint); + + if (!m_object || !m_object->documentFrameView()) + return E_FAIL; + + IntPoint point = m_object->documentFrameView()->screenToContents(IntPoint(x, y)); + AccessibilityObject* childObj = m_object->accessibilityHitTest(point); + + if (!childObj) { + // If we did not hit any child objects, test whether the point hit us, and + // report that. + if (!m_object->boundingBoxRect().contains(point)) + return S_FALSE; + childObj = m_object; + } + + if (childObj == m_object) { + V_VT(pvChildAtPoint) = VT_I4; + V_I4(pvChildAtPoint) = CHILDID_SELF; + } else { + V_VT(pvChildAtPoint) = VT_DISPATCH; + V_DISPATCH(pvChildAtPoint) = static_cast<IDispatch*>(wrapper(childObj)); + V_DISPATCH(pvChildAtPoint)->AddRef(); + } + return S_OK; +} + +HRESULT STDMETHODCALLTYPE AccessibleBase::accDoDefaultAction(VARIANT vChild) +{ + AccessibilityObject* childObj; + HRESULT hr = getAccessibilityObjectForChild(vChild, childObj); + + if (FAILED(hr)) + return hr; + + if (!childObj->performDefaultAction()) + return S_FALSE; + + return S_OK; +} + +// AccessibleBase +String AccessibleBase::name() const +{ + return m_object->nameForMSAA(); +} + +String AccessibleBase::value() const +{ + return m_object->stringValueForMSAA(); +} + +static long MSAARole(AccessibilityRole role) +{ + switch (role) { + case WebCore::ButtonRole: + return ROLE_SYSTEM_PUSHBUTTON; + case WebCore::RadioButtonRole: + return ROLE_SYSTEM_RADIOBUTTON; + case WebCore::CheckBoxRole: + return ROLE_SYSTEM_CHECKBUTTON; + case WebCore::SliderRole: + return ROLE_SYSTEM_SLIDER; + case WebCore::TabGroupRole: + return ROLE_SYSTEM_PAGETABLIST; + case WebCore::TextFieldRole: + case WebCore::TextAreaRole: + case WebCore::EditableTextRole: + return ROLE_SYSTEM_TEXT; + case WebCore::ListMarkerRole: + case WebCore::StaticTextRole: + return ROLE_SYSTEM_STATICTEXT; + case WebCore::OutlineRole: + return ROLE_SYSTEM_OUTLINE; + case WebCore::ColumnRole: + return ROLE_SYSTEM_COLUMN; + case WebCore::RowRole: + return ROLE_SYSTEM_ROW; + case WebCore::GroupRole: + return ROLE_SYSTEM_GROUPING; + case WebCore::ListRole: + case WebCore::ListBoxRole: + case WebCore::MenuListPopupRole: + return ROLE_SYSTEM_LIST; + case WebCore::TableRole: + return ROLE_SYSTEM_TABLE; + case WebCore::LinkRole: + case WebCore::WebCoreLinkRole: + return ROLE_SYSTEM_LINK; + case WebCore::ImageMapRole: + case WebCore::ImageRole: + return ROLE_SYSTEM_GRAPHIC; + case WebCore::MenuListOptionRole: + case WebCore::ListItemRole: + case WebCore::ListBoxOptionRole: + return ROLE_SYSTEM_LISTITEM; + case WebCore::PopUpButtonRole: + return ROLE_SYSTEM_COMBOBOX; + default: + // This is the default role for MSAA. + return ROLE_SYSTEM_CLIENT; + } +} + +long AccessibleBase::role() const +{ + return MSAARole(m_object->roleValueForMSAA()); +} + +HRESULT AccessibleBase::getAccessibilityObjectForChild(VARIANT vChild, AccessibilityObject*& childObj) const +{ + childObj = 0; + + if (!m_object) + return E_FAIL; + + if (vChild.vt != VT_I4) + return E_INVALIDARG; + + if (vChild.lVal == CHILDID_SELF) + childObj = m_object; + else if (vChild.lVal < 0) { + // When broadcasting MSAA events, we negate the AXID and pass it as the + // child ID. + Document* document = m_object->document(); + if (!document) + return E_FAIL; + + childObj = document->axObjectCache()->objectFromAXID(-vChild.lVal); + } else { + size_t childIndex = static_cast<size_t>(vChild.lVal - 1); + + if (childIndex >= m_object->children().size()) + return E_FAIL; + childObj = m_object->children().at(childIndex).get(); + } + + if (!childObj) + return E_FAIL; + + return S_OK; +} + +AccessibleBase* AccessibleBase::wrapper(AccessibilityObject* obj) +{ + AccessibleBase* result = static_cast<AccessibleBase*>(obj->wrapper()); + if (!result) + result = createInstance(obj); + return result; +} + +HRESULT AccessibleBase::isSameObject(IAccessibleComparable* other, BOOL* result) +{ + COMPtr<AccessibleBase> otherAccessibleBase(Query, other); + *result = (otherAccessibleBase == this || otherAccessibleBase->m_object == m_object); + return S_OK; +} |