| /* |
| * 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/PlatformKeyboardEvent.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 & PlatformKeyboardEvent::CtrlKey) |
| accessKeyModifiers += "Ctrl+"; |
| if (modifiers & PlatformKeyboardEvent::AltKey) |
| accessKeyModifiers += "Alt+"; |
| if (modifiers & PlatformKeyboardEvent::ShiftKey) |
| accessKeyModifiers += "Shift+"; |
| if (modifiers & PlatformKeyboardEvent::MetaKey) |
| accessKeyModifiers += "Win+"; |
| } |
| *shortcut = BString(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; |
| } |