AccessibleBase.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038
  1. /*
  2. * Copyright (C) 2008, 2009, 2010, 2013 Apple Inc. All Rights Reserved.
  3. * Copyright (C) 2012 Serotek Corporation. All Rights Reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
  15. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  17. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
  18. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  19. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  20. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  21. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  22. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "config.h"
  27. #include "WebKitDLL.h"
  28. #include "AccessibleBase.h"
  29. #include "AccessibleImage.h"
  30. #include "WebView.h"
  31. #include <WebCore/AccessibilityListBox.h>
  32. #include <WebCore/AccessibilityMenuListPopup.h>
  33. #include <WebCore/AccessibilityObject.h>
  34. #include <WebCore/AXObjectCache.h>
  35. #include <WebCore/BString.h>
  36. #include <WebCore/Element.h>
  37. #include <WebCore/EventHandler.h>
  38. #include <WebCore/FrameView.h>
  39. #include <WebCore/HostWindow.h>
  40. #include <WebCore/HTMLNames.h>
  41. #include <WebCore/HTMLFrameElementBase.h>
  42. #include <WebCore/HTMLInputElement.h>
  43. #include <WebCore/IntRect.h>
  44. #include <WebCore/NotImplemented.h>
  45. #include <WebCore/PlatformEvent.h>
  46. #include <WebCore/RenderFrame.h>
  47. #include <WebCore/RenderObject.h>
  48. #include <WebCore/RenderView.h>
  49. #include <comutil.h>
  50. #include <oleacc.h>
  51. #include <wtf/RefPtr.h>
  52. #include <wtf/text/StringBuilder.h>
  53. using namespace WebCore;
  54. AccessibleBase::AccessibleBase(AccessibilityObject* obj, HWND window)
  55. : AccessibilityObjectWrapper(obj)
  56. , m_window(window)
  57. , m_refCount(0)
  58. {
  59. ASSERT_ARG(obj, obj);
  60. m_object->setWrapper(this);
  61. ++gClassCount;
  62. gClassNameCount.add("AccessibleBase");
  63. }
  64. AccessibleBase::~AccessibleBase()
  65. {
  66. --gClassCount;
  67. gClassNameCount.remove("AccessibleBase");
  68. }
  69. AccessibleBase* AccessibleBase::createInstance(AccessibilityObject* obj, HWND window)
  70. {
  71. ASSERT_ARG(obj, obj);
  72. if (obj->isImage())
  73. return new AccessibleImage(obj, window);
  74. return new AccessibleBase(obj, window);
  75. }
  76. HRESULT AccessibleBase::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
  77. {
  78. if (!IsEqualGUID(guidService, SID_AccessibleComparable)
  79. && !IsEqualGUID(guidService, IID_IAccessible2_2)
  80. && !IsEqualGUID(guidService, IID_IAccessible2)
  81. && !IsEqualGUID(guidService, IID_IAccessibleApplication)
  82. && !IsEqualGUID(guidService, IID_IAccessible)) {
  83. *ppvObject = 0;
  84. return E_INVALIDARG;
  85. }
  86. return QueryInterface(riid, ppvObject);
  87. }
  88. // IUnknown
  89. HRESULT STDMETHODCALLTYPE AccessibleBase::QueryInterface(REFIID riid, void** ppvObject)
  90. {
  91. if (IsEqualGUID(riid, __uuidof(IAccessible)))
  92. *ppvObject = static_cast<IAccessible*>(this);
  93. else if (IsEqualGUID(riid, __uuidof(IDispatch)))
  94. *ppvObject = static_cast<IAccessible*>(this);
  95. else if (IsEqualGUID(riid, __uuidof(IUnknown)))
  96. *ppvObject = static_cast<IAccessible*>(this);
  97. else if (IsEqualGUID(riid, __uuidof(IAccessible2_2)))
  98. *ppvObject = static_cast<IAccessible2_2*>(this);
  99. else if (IsEqualGUID(riid, __uuidof(IAccessible2)))
  100. *ppvObject = static_cast<IAccessible2*>(this);
  101. else if (IsEqualGUID(riid, __uuidof(IAccessibleComparable)))
  102. *ppvObject = static_cast<IAccessibleComparable*>(this);
  103. else if (IsEqualGUID(riid, __uuidof(IServiceProvider)))
  104. *ppvObject = static_cast<IServiceProvider*>(this);
  105. else if (IsEqualGUID(riid, __uuidof(AccessibleBase)))
  106. *ppvObject = static_cast<AccessibleBase*>(this);
  107. else {
  108. *ppvObject = 0;
  109. return E_NOINTERFACE;
  110. }
  111. AddRef();
  112. return S_OK;
  113. }
  114. ULONG STDMETHODCALLTYPE AccessibleBase::Release(void)
  115. {
  116. ASSERT(m_refCount > 0);
  117. if (--m_refCount)
  118. return m_refCount;
  119. delete this;
  120. return 0;
  121. }
  122. // IAccessible2_2
  123. HRESULT AccessibleBase::get_attribute(BSTR key, VARIANT* value)
  124. {
  125. if (!value)
  126. return E_POINTER;
  127. AtomicString keyAtomic(key, ::SysStringLen(key));
  128. accessibilityAttributeValue(keyAtomic, value);
  129. return S_OK;
  130. }
  131. HRESULT AccessibleBase::get_accessibleWithCaret(IUnknown** accessible, long* caretOffset)
  132. {
  133. notImplemented();
  134. return E_NOTIMPL;
  135. }
  136. HRESULT AccessibleBase::get_relationTargetsOfType(BSTR type, long maxTargets, IUnknown*** targets, long* nTargets)
  137. {
  138. notImplemented();
  139. return E_NOTIMPL;
  140. }
  141. // IAccessible2
  142. HRESULT AccessibleBase::get_nRelations(long* nRelations)
  143. {
  144. if (!nRelations)
  145. return E_POINTER;
  146. if (!m_object)
  147. return E_FAIL;
  148. notImplemented();
  149. *nRelations = 0;
  150. return S_OK;
  151. }
  152. HRESULT AccessibleBase::get_relation(long relationIndex, IAccessibleRelation** relation)
  153. {
  154. if (!relation)
  155. return E_POINTER;
  156. notImplemented();
  157. return E_NOTIMPL;
  158. }
  159. HRESULT AccessibleBase::get_relations(long maxRelations, IAccessibleRelation** relations, long* nRelations)
  160. {
  161. if (!relations || !nRelations)
  162. return E_POINTER;
  163. notImplemented();
  164. return E_NOTIMPL;
  165. }
  166. HRESULT AccessibleBase::role(long* role)
  167. {
  168. if (!role)
  169. return E_POINTER;
  170. if (!m_object)
  171. return E_FAIL;
  172. *role = wrapper(m_object)->role();
  173. return S_OK;
  174. }
  175. HRESULT AccessibleBase::scrollTo(IA2ScrollType scrollType)
  176. {
  177. if (!m_object)
  178. return E_FAIL;
  179. return S_FALSE;
  180. }
  181. HRESULT AccessibleBase::scrollToPoint(IA2CoordinateType coordinateType, long x, long y)
  182. {
  183. if (!m_object)
  184. return E_FAIL;
  185. return S_FALSE;
  186. }
  187. HRESULT AccessibleBase::get_groupPosition(long* groupLevel, long* similarItemsInGroup, long* positionInGroup)
  188. {
  189. notImplemented();
  190. return E_NOTIMPL;
  191. }
  192. HRESULT AccessibleBase::get_states(AccessibleStates* states)
  193. {
  194. if (!states)
  195. return E_POINTER;
  196. if (!m_object)
  197. return E_FAIL;
  198. *states = 0;
  199. notImplemented();
  200. return S_OK;
  201. }
  202. HRESULT AccessibleBase::get_extendedRole(BSTR* extendedRole)
  203. {
  204. if (!extendedRole)
  205. return E_POINTER;
  206. if (!m_object)
  207. return E_FAIL;
  208. notImplemented();
  209. return S_FALSE;
  210. }
  211. HRESULT AccessibleBase::get_localizedExtendedRole(BSTR* localizedExtendedRole)
  212. {
  213. if (!localizedExtendedRole)
  214. return E_POINTER;
  215. if (!m_object)
  216. return E_FAIL;
  217. notImplemented();
  218. return S_FALSE;
  219. }
  220. HRESULT AccessibleBase::get_nExtendedStates(long* nExtendedStates)
  221. {
  222. if (!nExtendedStates)
  223. return E_POINTER;
  224. if (!m_object)
  225. return E_FAIL;
  226. notImplemented();
  227. *nExtendedStates = 0;
  228. return S_OK;
  229. }
  230. HRESULT AccessibleBase::get_extendedStates(long maxExtendedStates, BSTR** extendedStates, long* nExtendedStates)
  231. {
  232. notImplemented();
  233. return E_NOTIMPL;
  234. }
  235. HRESULT AccessibleBase::get_localizedExtendedStates(long maxLocalizedExtendedStates, BSTR** localizedExtendedStates, long* nLocalizedExtendedStates)
  236. {
  237. notImplemented();
  238. return E_NOTIMPL;
  239. }
  240. HRESULT AccessibleBase::get_uniqueID(long* uniqueID)
  241. {
  242. if (!uniqueID)
  243. return E_POINTER;
  244. if (!m_object)
  245. return E_FAIL;
  246. *uniqueID = static_cast<long>(m_object->axObjectID());
  247. return S_OK;
  248. }
  249. HRESULT AccessibleBase::get_windowHandle(HWND* windowHandle)
  250. {
  251. *windowHandle = m_window;
  252. return S_OK;
  253. }
  254. HRESULT AccessibleBase::get_indexInParent(long* indexInParent)
  255. {
  256. return E_NOTIMPL;
  257. }
  258. HRESULT AccessibleBase::get_locale(IA2Locale* locale)
  259. {
  260. notImplemented();
  261. return E_NOTIMPL;
  262. }
  263. HRESULT AccessibleBase::get_attributes(BSTR* attributes)
  264. {
  265. if (!m_object)
  266. return E_FAIL;
  267. notImplemented();
  268. return S_FALSE;
  269. }
  270. // IAccessible
  271. HRESULT AccessibleBase::get_accParent(IDispatch** parent)
  272. {
  273. *parent = 0;
  274. if (!m_object)
  275. return E_FAIL;
  276. AccessibilityObject* parentObject = m_object->parentObjectUnignored();
  277. if (parentObject) {
  278. *parent = wrapper(parentObject);
  279. (*parent)->AddRef();
  280. return S_OK;
  281. }
  282. if (!m_window)
  283. return E_FAIL;
  284. return WebView::AccessibleObjectFromWindow(m_window,
  285. OBJID_WINDOW, __uuidof(IAccessible), reinterpret_cast<void**>(parent));
  286. }
  287. HRESULT STDMETHODCALLTYPE AccessibleBase::get_accChildCount(long* count)
  288. {
  289. if (!m_object)
  290. return E_FAIL;
  291. if (!count)
  292. return E_POINTER;
  293. *count = static_cast<long>(m_object->children().size());
  294. return S_OK;
  295. }
  296. HRESULT STDMETHODCALLTYPE AccessibleBase::get_accChild(VARIANT vChild, IDispatch** ppChild)
  297. {
  298. if (!ppChild)
  299. return E_POINTER;
  300. *ppChild = 0;
  301. AccessibilityObject* childObj;
  302. HRESULT hr = getAccessibilityObjectForChild(vChild, childObj);
  303. if (FAILED(hr))
  304. return hr;
  305. *ppChild = static_cast<IDispatch*>(wrapper(childObj));
  306. (*ppChild)->AddRef();
  307. return S_OK;
  308. }
  309. HRESULT STDMETHODCALLTYPE AccessibleBase::get_accName(VARIANT vChild, BSTR* name)
  310. {
  311. if (!name)
  312. return E_POINTER;
  313. *name = 0;
  314. AccessibilityObject* childObj;
  315. HRESULT hr = getAccessibilityObjectForChild(vChild, childObj);
  316. if (FAILED(hr))
  317. return hr;
  318. if (*name = BString(wrapper(childObj)->name()).release())
  319. return S_OK;
  320. return S_FALSE;
  321. }
  322. HRESULT STDMETHODCALLTYPE AccessibleBase::get_accValue(VARIANT vChild, BSTR* value)
  323. {
  324. if (!value)
  325. return E_POINTER;
  326. *value = 0;
  327. AccessibilityObject* childObj;
  328. HRESULT hr = getAccessibilityObjectForChild(vChild, childObj);
  329. if (FAILED(hr))
  330. return hr;
  331. if (*value = BString(wrapper(childObj)->value()).release())
  332. return S_OK;
  333. return S_FALSE;
  334. }
  335. HRESULT STDMETHODCALLTYPE AccessibleBase::get_accDescription(VARIANT vChild, BSTR* description)
  336. {
  337. if (!description)
  338. return E_POINTER;
  339. *description = 0;
  340. AccessibilityObject* childObj;
  341. HRESULT hr = getAccessibilityObjectForChild(vChild, childObj);
  342. if (FAILED(hr))
  343. return hr;
  344. if (*description = BString(childObj->descriptionForMSAA()).release())
  345. return S_OK;
  346. return S_FALSE;
  347. }
  348. HRESULT STDMETHODCALLTYPE AccessibleBase::get_accRole(VARIANT vChild, VARIANT* pvRole)
  349. {
  350. if (!pvRole)
  351. return E_POINTER;
  352. ::VariantInit(pvRole);
  353. AccessibilityObject* childObj;
  354. HRESULT hr = getAccessibilityObjectForChild(vChild, childObj);
  355. if (FAILED(hr))
  356. return hr;
  357. String roleString = childObj->stringRoleForMSAA();
  358. if (!roleString.isEmpty()) {
  359. V_VT(pvRole) = VT_BSTR;
  360. V_BSTR(pvRole) = BString(roleString).release();
  361. return S_OK;
  362. }
  363. pvRole->vt = VT_I4;
  364. pvRole->lVal = wrapper(childObj)->role();
  365. return S_OK;
  366. }
  367. long AccessibleBase::state() const
  368. {
  369. long state = 0;
  370. if (m_object->isLinked())
  371. state |= STATE_SYSTEM_LINKED;
  372. if (m_object->isHovered())
  373. state |= STATE_SYSTEM_HOTTRACKED;
  374. if (!m_object->isEnabled())
  375. state |= STATE_SYSTEM_UNAVAILABLE;
  376. if (m_object->isReadOnly())
  377. state |= STATE_SYSTEM_READONLY;
  378. if (m_object->isOffScreen())
  379. state |= STATE_SYSTEM_OFFSCREEN;
  380. if (m_object->isPasswordField())
  381. state |= STATE_SYSTEM_PROTECTED;
  382. if (m_object->isIndeterminate())
  383. state |= STATE_SYSTEM_INDETERMINATE;
  384. if (m_object->isChecked())
  385. state |= STATE_SYSTEM_CHECKED;
  386. if (m_object->isPressed())
  387. state |= STATE_SYSTEM_PRESSED;
  388. if (m_object->isFocused())
  389. state |= STATE_SYSTEM_FOCUSED;
  390. if (m_object->isVisited())
  391. state |= STATE_SYSTEM_TRAVERSED;
  392. if (m_object->canSetFocusAttribute())
  393. state |= STATE_SYSTEM_FOCUSABLE;
  394. if (m_object->isSelected())
  395. state |= STATE_SYSTEM_SELECTED;
  396. if (m_object->canSetSelectedAttribute())
  397. state |= STATE_SYSTEM_SELECTABLE;
  398. if (m_object->isMultiSelectable())
  399. state |= STATE_SYSTEM_EXTSELECTABLE | STATE_SYSTEM_MULTISELECTABLE;
  400. if (!m_object->isVisible())
  401. state |= STATE_SYSTEM_INVISIBLE;
  402. if (m_object->isCollapsed())
  403. state |= STATE_SYSTEM_COLLAPSED;
  404. if (m_object->roleValue() == PopUpButtonRole) {
  405. state |= STATE_SYSTEM_HASPOPUP;
  406. if (!m_object->isCollapsed())
  407. state |= STATE_SYSTEM_EXPANDED;
  408. }
  409. return state;
  410. }
  411. HRESULT AccessibleBase::get_accState(VARIANT vChild, VARIANT* pvState)
  412. {
  413. if (!pvState)
  414. return E_POINTER;
  415. ::VariantInit(pvState);
  416. AccessibilityObject* childObj;
  417. HRESULT hr = getAccessibilityObjectForChild(vChild, childObj);
  418. if (FAILED(hr))
  419. return hr;
  420. pvState->vt = VT_I4;
  421. pvState->lVal = wrapper(childObj)->state();
  422. return S_OK;
  423. }
  424. HRESULT STDMETHODCALLTYPE AccessibleBase::get_accHelp(VARIANT vChild, BSTR* helpText)
  425. {
  426. if (!helpText)
  427. return E_POINTER;
  428. *helpText = 0;
  429. AccessibilityObject* childObj;
  430. HRESULT hr = getAccessibilityObjectForChild(vChild, childObj);
  431. if (FAILED(hr))
  432. return hr;
  433. if (*helpText = BString(childObj->helpText()).release())
  434. return S_OK;
  435. return S_FALSE;
  436. }
  437. HRESULT STDMETHODCALLTYPE AccessibleBase::get_accKeyboardShortcut(VARIANT vChild, BSTR* shortcut)
  438. {
  439. if (!shortcut)
  440. return E_POINTER;
  441. *shortcut = 0;
  442. AccessibilityObject* childObj;
  443. HRESULT hr = getAccessibilityObjectForChild(vChild, childObj);
  444. if (FAILED(hr))
  445. return hr;
  446. String accessKey = childObj->accessKey();
  447. if (accessKey.isNull())
  448. return S_FALSE;
  449. static String accessKeyModifiers;
  450. if (accessKeyModifiers.isNull()) {
  451. StringBuilder accessKeyModifiersBuilder;
  452. unsigned modifiers = EventHandler::accessKeyModifiers();
  453. // Follow the same order as Mozilla MSAA implementation:
  454. // Ctrl+Alt+Shift+Meta+key. MSDN states that keyboard shortcut strings
  455. // should not be localized and defines the separator as "+".
  456. if (modifiers & PlatformEvent::CtrlKey)
  457. accessKeyModifiersBuilder.appendLiteral("Ctrl+");
  458. if (modifiers & PlatformEvent::AltKey)
  459. accessKeyModifiersBuilder.appendLiteral("Alt+");
  460. if (modifiers & PlatformEvent::ShiftKey)
  461. accessKeyModifiersBuilder.appendLiteral("Shift+");
  462. if (modifiers & PlatformEvent::MetaKey)
  463. accessKeyModifiersBuilder.appendLiteral("Win+");
  464. accessKeyModifiers = accessKeyModifiersBuilder.toString();
  465. }
  466. *shortcut = BString(String(accessKeyModifiers + accessKey)).release();
  467. return S_OK;
  468. }
  469. HRESULT STDMETHODCALLTYPE AccessibleBase::accSelect(long selectionFlags, VARIANT vChild)
  470. {
  471. // According to MSDN, these combinations are invalid.
  472. if (((selectionFlags & (SELFLAG_ADDSELECTION | SELFLAG_REMOVESELECTION)) == (SELFLAG_ADDSELECTION | SELFLAG_REMOVESELECTION))
  473. || ((selectionFlags & (SELFLAG_ADDSELECTION | SELFLAG_TAKESELECTION)) == (SELFLAG_ADDSELECTION | SELFLAG_TAKESELECTION))
  474. || ((selectionFlags & (SELFLAG_REMOVESELECTION | SELFLAG_TAKESELECTION)) == (SELFLAG_REMOVESELECTION | SELFLAG_TAKESELECTION))
  475. || ((selectionFlags & (SELFLAG_EXTENDSELECTION | SELFLAG_TAKESELECTION)) == (SELFLAG_EXTENDSELECTION | SELFLAG_TAKESELECTION)))
  476. return E_INVALIDARG;
  477. AccessibilityObject* childObject;
  478. HRESULT hr = getAccessibilityObjectForChild(vChild, childObject);
  479. if (FAILED(hr))
  480. return hr;
  481. if (selectionFlags & SELFLAG_TAKEFOCUS)
  482. childObject->setFocused(true);
  483. AccessibilityObject* parentObject = childObject->parentObject();
  484. if (!parentObject)
  485. return E_INVALIDARG;
  486. if (selectionFlags & SELFLAG_TAKESELECTION) {
  487. if (parentObject->isListBox()) {
  488. Vector<RefPtr<AccessibilityObject> > selectedChildren(1);
  489. selectedChildren[0] = childObject;
  490. static_cast<AccessibilityListBox*>(parentObject)->setSelectedChildren(selectedChildren);
  491. } else { // any element may be selectable by virtue of it having the aria-selected property
  492. ASSERT(!parentObject->isMultiSelectable());
  493. childObject->setSelected(true);
  494. }
  495. }
  496. // MSDN says that ADD, REMOVE, and EXTENDSELECTION with no other flags are invalid for
  497. // single-select.
  498. const long allSELFLAGs = SELFLAG_TAKEFOCUS | SELFLAG_TAKESELECTION | SELFLAG_EXTENDSELECTION | SELFLAG_ADDSELECTION | SELFLAG_REMOVESELECTION;
  499. if (!parentObject->isMultiSelectable()
  500. && (((selectionFlags & allSELFLAGs) == SELFLAG_ADDSELECTION)
  501. || ((selectionFlags & allSELFLAGs) == SELFLAG_REMOVESELECTION)
  502. || ((selectionFlags & allSELFLAGs) == SELFLAG_EXTENDSELECTION)))
  503. return E_INVALIDARG;
  504. if (selectionFlags & SELFLAG_ADDSELECTION)
  505. childObject->setSelected(true);
  506. if (selectionFlags & SELFLAG_REMOVESELECTION)
  507. childObject->setSelected(false);
  508. // FIXME: Should implement SELFLAG_EXTENDSELECTION. For now, we just return
  509. // S_OK, matching Firefox.
  510. return S_OK;
  511. }
  512. HRESULT STDMETHODCALLTYPE AccessibleBase::get_accSelection(VARIANT*)
  513. {
  514. return E_NOTIMPL;
  515. }
  516. HRESULT STDMETHODCALLTYPE AccessibleBase::get_accFocus(VARIANT* pvFocusedChild)
  517. {
  518. if (!pvFocusedChild)
  519. return E_POINTER;
  520. ::VariantInit(pvFocusedChild);
  521. if (!m_object)
  522. return E_FAIL;
  523. AccessibilityObject* focusedObj = m_object->focusedUIElement();
  524. if (!focusedObj)
  525. return S_FALSE;
  526. if (focusedObj == m_object) {
  527. V_VT(pvFocusedChild) = VT_I4;
  528. V_I4(pvFocusedChild) = CHILDID_SELF;
  529. return S_OK;
  530. }
  531. V_VT(pvFocusedChild) = VT_DISPATCH;
  532. V_DISPATCH(pvFocusedChild) = wrapper(focusedObj);
  533. V_DISPATCH(pvFocusedChild)->AddRef();
  534. return S_OK;
  535. }
  536. HRESULT STDMETHODCALLTYPE AccessibleBase::get_accDefaultAction(VARIANT vChild, BSTR* action)
  537. {
  538. if (!action)
  539. return E_POINTER;
  540. *action = 0;
  541. AccessibilityObject* childObj;
  542. HRESULT hr = getAccessibilityObjectForChild(vChild, childObj);
  543. if (FAILED(hr))
  544. return hr;
  545. if (*action = BString(childObj->actionVerb()).release())
  546. return S_OK;
  547. return S_FALSE;
  548. }
  549. HRESULT STDMETHODCALLTYPE AccessibleBase::accLocation(long* left, long* top, long* width, long* height, VARIANT vChild)
  550. {
  551. if (!left || !top || !width || !height)
  552. return E_POINTER;
  553. *left = *top = *width = *height = 0;
  554. AccessibilityObject* childObj;
  555. HRESULT hr = getAccessibilityObjectForChild(vChild, childObj);
  556. if (FAILED(hr))
  557. return hr;
  558. if (!childObj->documentFrameView())
  559. return E_FAIL;
  560. IntRect screenRect(childObj->documentFrameView()->contentsToScreen(childObj->pixelSnappedElementRect()));
  561. *left = screenRect.x();
  562. *top = screenRect.y();
  563. *width = screenRect.width();
  564. *height = screenRect.height();
  565. return S_OK;
  566. }
  567. HRESULT STDMETHODCALLTYPE AccessibleBase::accNavigate(long direction, VARIANT vFromChild, VARIANT* pvNavigatedTo)
  568. {
  569. if (!pvNavigatedTo)
  570. return E_POINTER;
  571. ::VariantInit(pvNavigatedTo);
  572. AccessibilityObject* childObj = 0;
  573. switch (direction) {
  574. case NAVDIR_DOWN:
  575. case NAVDIR_UP:
  576. case NAVDIR_LEFT:
  577. case NAVDIR_RIGHT:
  578. // These directions are not implemented, matching Mozilla and IE.
  579. return E_NOTIMPL;
  580. case NAVDIR_LASTCHILD:
  581. case NAVDIR_FIRSTCHILD:
  582. // MSDN states that navigating to first/last child can only be from self.
  583. if (vFromChild.lVal != CHILDID_SELF)
  584. return E_INVALIDARG;
  585. if (!m_object)
  586. return E_FAIL;
  587. if (direction == NAVDIR_FIRSTCHILD)
  588. childObj = m_object->firstChild();
  589. else
  590. childObj = m_object->lastChild();
  591. break;
  592. case NAVDIR_NEXT:
  593. case NAVDIR_PREVIOUS: {
  594. // Navigating to next and previous is allowed from self or any of our children.
  595. HRESULT hr = getAccessibilityObjectForChild(vFromChild, childObj);
  596. if (FAILED(hr))
  597. return hr;
  598. if (direction == NAVDIR_NEXT)
  599. childObj = childObj->nextSibling();
  600. else
  601. childObj = childObj->previousSibling();
  602. break;
  603. }
  604. default:
  605. ASSERT_NOT_REACHED();
  606. return E_INVALIDARG;
  607. }
  608. if (!childObj)
  609. return S_FALSE;
  610. V_VT(pvNavigatedTo) = VT_DISPATCH;
  611. V_DISPATCH(pvNavigatedTo) = wrapper(childObj);
  612. V_DISPATCH(pvNavigatedTo)->AddRef();
  613. return S_OK;
  614. }
  615. HRESULT STDMETHODCALLTYPE AccessibleBase::accHitTest(long x, long y, VARIANT* pvChildAtPoint)
  616. {
  617. if (!pvChildAtPoint)
  618. return E_POINTER;
  619. ::VariantInit(pvChildAtPoint);
  620. if (!m_object || !m_object->documentFrameView())
  621. return E_FAIL;
  622. IntPoint point = m_object->documentFrameView()->screenToContents(IntPoint(x, y));
  623. AccessibilityObject* childObj = m_object->accessibilityHitTest(point);
  624. if (!childObj) {
  625. // If we did not hit any child objects, test whether the point hit us, and
  626. // report that.
  627. if (!m_object->boundingBoxRect().contains(point))
  628. return S_FALSE;
  629. childObj = m_object;
  630. }
  631. if (childObj == m_object) {
  632. V_VT(pvChildAtPoint) = VT_I4;
  633. V_I4(pvChildAtPoint) = CHILDID_SELF;
  634. } else {
  635. V_VT(pvChildAtPoint) = VT_DISPATCH;
  636. V_DISPATCH(pvChildAtPoint) = static_cast<IDispatch*>(wrapper(childObj));
  637. V_DISPATCH(pvChildAtPoint)->AddRef();
  638. }
  639. return S_OK;
  640. }
  641. HRESULT STDMETHODCALLTYPE AccessibleBase::accDoDefaultAction(VARIANT vChild)
  642. {
  643. AccessibilityObject* childObj;
  644. HRESULT hr = getAccessibilityObjectForChild(vChild, childObj);
  645. if (FAILED(hr))
  646. return hr;
  647. if (!childObj->performDefaultAction())
  648. return S_FALSE;
  649. return S_OK;
  650. }
  651. // AccessibleBase
  652. String AccessibleBase::name() const
  653. {
  654. return m_object->nameForMSAA();
  655. }
  656. String AccessibleBase::value() const
  657. {
  658. return m_object->stringValueForMSAA();
  659. }
  660. static long MSAARole(AccessibilityRole role)
  661. {
  662. switch (role) {
  663. case WebCore::ButtonRole:
  664. return ROLE_SYSTEM_PUSHBUTTON;
  665. case WebCore::RadioButtonRole:
  666. return ROLE_SYSTEM_RADIOBUTTON;
  667. case WebCore::CheckBoxRole:
  668. return ROLE_SYSTEM_CHECKBUTTON;
  669. case WebCore::SliderRole:
  670. return ROLE_SYSTEM_SLIDER;
  671. case WebCore::TabGroupRole:
  672. case WebCore::TabListRole:
  673. return ROLE_SYSTEM_PAGETABLIST;
  674. case WebCore::TextFieldRole:
  675. case WebCore::TextAreaRole:
  676. case WebCore::EditableTextRole:
  677. return ROLE_SYSTEM_TEXT;
  678. case WebCore::HeadingRole:
  679. case WebCore::ListMarkerRole:
  680. case WebCore::StaticTextRole:
  681. return ROLE_SYSTEM_STATICTEXT;
  682. case WebCore::OutlineRole:
  683. return ROLE_SYSTEM_OUTLINE;
  684. case WebCore::ColumnRole:
  685. return ROLE_SYSTEM_COLUMN;
  686. case WebCore::RowRole:
  687. return ROLE_SYSTEM_ROW;
  688. case WebCore::GroupRole:
  689. case WebCore::RadioGroupRole:
  690. return ROLE_SYSTEM_GROUPING;
  691. case WebCore::DescriptionListRole:
  692. case WebCore::DirectoryRole:
  693. case WebCore::ListRole:
  694. case WebCore::ListBoxRole:
  695. case WebCore::MenuListPopupRole:
  696. return ROLE_SYSTEM_LIST;
  697. case WebCore::GridRole:
  698. case WebCore::TableRole:
  699. return ROLE_SYSTEM_TABLE;
  700. case WebCore::ImageMapLinkRole:
  701. case WebCore::LinkRole:
  702. case WebCore::WebCoreLinkRole:
  703. return ROLE_SYSTEM_LINK;
  704. case WebCore::CanvasRole:
  705. case WebCore::ImageMapRole:
  706. case WebCore::ImageRole:
  707. return ROLE_SYSTEM_GRAPHIC;
  708. case WebCore::ListItemRole:
  709. return ROLE_SYSTEM_LISTITEM;
  710. case WebCore::ListBoxOptionRole:
  711. case WebCore::MenuListOptionRole:
  712. return ROLE_SYSTEM_STATICTEXT;
  713. case WebCore::ComboBoxRole:
  714. case WebCore::PopUpButtonRole:
  715. return ROLE_SYSTEM_COMBOBOX;
  716. case WebCore::DivRole:
  717. case WebCore::FooterRole:
  718. case WebCore::FormRole:
  719. case WebCore::LabelRole:
  720. case WebCore::ParagraphRole:
  721. return ROLE_SYSTEM_GROUPING;
  722. case WebCore::HorizontalRuleRole:
  723. case WebCore::SplitterRole:
  724. return ROLE_SYSTEM_SEPARATOR;
  725. case WebCore::ApplicationAlertRole:
  726. case WebCore::ApplicationAlertDialogRole:
  727. return ROLE_SYSTEM_ALERT;
  728. case WebCore::DisclosureTriangleRole:
  729. return ROLE_SYSTEM_BUTTONDROPDOWN;
  730. case WebCore::SeamlessWebAreaRole:
  731. return ROLE_SYSTEM_GROUPING;
  732. case WebCore::IncrementorRole:
  733. case WebCore::SpinButtonRole:
  734. return ROLE_SYSTEM_SPINBUTTON;
  735. case WebCore::SpinButtonPartRole:
  736. return ROLE_SYSTEM_PUSHBUTTON;
  737. case WebCore::ToggleButtonRole:
  738. return ROLE_SYSTEM_PUSHBUTTON;
  739. case WebCore::ToolbarRole:
  740. return ROLE_SYSTEM_TOOLBAR;
  741. case WebCore::UserInterfaceTooltipRole:
  742. return ROLE_SYSTEM_TOOLTIP;
  743. case WebCore::TreeRole:
  744. case WebCore::TreeGridRole:
  745. return ROLE_SYSTEM_OUTLINE;
  746. case WebCore::TreeItemRole:
  747. return ROLE_SYSTEM_OUTLINEITEM;
  748. case WebCore::TabPanelRole:
  749. return ROLE_SYSTEM_GROUPING;
  750. case WebCore::TabRole:
  751. return ROLE_SYSTEM_PAGETAB;
  752. case WebCore::ApplicationRole:
  753. return ROLE_SYSTEM_APPLICATION;
  754. case WebCore::ApplicationDialogRole:
  755. return ROLE_SYSTEM_DIALOG;
  756. case WebCore::ApplicationLogRole:
  757. case WebCore::ApplicationMarqueeRole:
  758. return ROLE_SYSTEM_GROUPING;
  759. case WebCore::ApplicationStatusRole:
  760. return ROLE_SYSTEM_STATUSBAR;
  761. case WebCore::ApplicationTimerRole:
  762. return ROLE_SYSTEM_CLOCK;
  763. case WebCore::CellRole:
  764. return ROLE_SYSTEM_CELL;
  765. case WebCore::ColumnHeaderRole:
  766. return ROLE_SYSTEM_COLUMNHEADER;
  767. case WebCore::DefinitionRole:
  768. case WebCore::DescriptionListDetailRole:
  769. case WebCore::DescriptionListTermRole:
  770. case WebCore::DocumentRole:
  771. case WebCore::DocumentArticleRole:
  772. case WebCore::DocumentNoteRole:
  773. case WebCore::DocumentRegionRole:
  774. return ROLE_SYSTEM_GROUPING;
  775. case WebCore::DocumentMathRole:
  776. case WebCore::MathElementRole:
  777. return ROLE_SYSTEM_EQUATION;
  778. case WebCore::HelpTagRole:
  779. return ROLE_SYSTEM_HELPBALLOON;
  780. case WebCore::LandmarkApplicationRole:
  781. case WebCore::LandmarkBannerRole:
  782. case WebCore::LandmarkComplementaryRole:
  783. case WebCore::LandmarkContentInfoRole:
  784. case WebCore::LandmarkMainRole:
  785. case WebCore::LandmarkNavigationRole:
  786. case WebCore::LandmarkSearchRole:
  787. case WebCore::LegendRole:
  788. return ROLE_SYSTEM_GROUPING;
  789. case WebCore::MenuRole:
  790. return ROLE_SYSTEM_MENUPOPUP;
  791. case WebCore::MenuItemRole:
  792. case WebCore::MenuButtonRole:
  793. return ROLE_SYSTEM_MENUITEM;
  794. case WebCore::MenuBarRole:
  795. return ROLE_SYSTEM_MENUBAR;
  796. case WebCore::ProgressIndicatorRole:
  797. return ROLE_SYSTEM_PROGRESSBAR;
  798. case WebCore::RowHeaderRole:
  799. return ROLE_SYSTEM_ROWHEADER;
  800. case WebCore::ScrollBarRole:
  801. return ROLE_SYSTEM_SCROLLBAR;
  802. case WebCore::SVGRootRole:
  803. return ROLE_SYSTEM_GROUPING;
  804. case WebCore::TableHeaderContainerRole:
  805. return ROLE_SYSTEM_GROUPING;
  806. case WebCore::WindowRole:
  807. return ROLE_SYSTEM_WINDOW;
  808. default:
  809. // This is the default role for MSAA.
  810. return ROLE_SYSTEM_CLIENT;
  811. }
  812. }
  813. long AccessibleBase::role() const
  814. {
  815. return MSAARole(m_object->roleValueForMSAA());
  816. }
  817. HRESULT AccessibleBase::getAccessibilityObjectForChild(VARIANT vChild, AccessibilityObject*& childObj) const
  818. {
  819. childObj = 0;
  820. if (!m_object)
  821. return E_FAIL;
  822. if (vChild.vt != VT_I4)
  823. return E_INVALIDARG;
  824. if (vChild.lVal == CHILDID_SELF)
  825. childObj = m_object;
  826. else if (vChild.lVal < 0) {
  827. // When broadcasting MSAA events, we negate the AXID and pass it as the
  828. // child ID.
  829. Document* document = m_object->document();
  830. if (!document)
  831. return E_FAIL;
  832. childObj = document->axObjectCache()->objectFromAXID(-vChild.lVal);
  833. } else {
  834. size_t childIndex = static_cast<size_t>(vChild.lVal - 1);
  835. if (childIndex >= m_object->children().size())
  836. return E_FAIL;
  837. childObj = m_object->children().at(childIndex).get();
  838. }
  839. if (!childObj)
  840. return E_FAIL;
  841. return S_OK;
  842. }
  843. AccessibleBase* AccessibleBase::wrapper(AccessibilityObject* obj) const
  844. {
  845. AccessibleBase* result = static_cast<AccessibleBase*>(obj->wrapper());
  846. if (!result)
  847. result = createInstance(obj, m_window);
  848. return result;
  849. }
  850. HRESULT AccessibleBase::isSameObject(IAccessibleComparable* other, BOOL* result)
  851. {
  852. COMPtr<AccessibleBase> otherAccessibleBase(Query, other);
  853. *result = (otherAccessibleBase == this || otherAccessibleBase->m_object == m_object);
  854. return S_OK;
  855. }