Bug 1869092 - Fix timeouts in browser_PanelMultiView.js. r=twisniewski,test-only
[gecko.git] / accessible / mac / AccessibleWrap.mm
blobef2f4ba779ec1920a1684136c5466e14d66bc45a
1 /* clang-format off */
2 /* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
3 /* clang-format on */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "DocAccessibleWrap.h"
9 #include "nsObjCExceptions.h"
10 #include "nsCocoaUtils.h"
11 #include "nsUnicharUtils.h"
13 #include "LocalAccessible-inl.h"
14 #include "nsAccUtils.h"
15 #include "mozilla/a11y/Role.h"
16 #include "TextRange.h"
17 #include "gfxPlatform.h"
19 #import "MOXLandmarkAccessibles.h"
20 #import "MOXMathAccessibles.h"
21 #import "MOXTextMarkerDelegate.h"
22 #import "MOXWebAreaAccessible.h"
23 #import "mozAccessible.h"
24 #import "mozActionElements.h"
25 #import "mozHTMLAccessible.h"
26 #import "mozSelectableElements.h"
27 #import "mozTableAccessible.h"
28 #import "mozTextAccessible.h"
30 using namespace mozilla;
31 using namespace mozilla::a11y;
33 AccessibleWrap::AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc)
34     : LocalAccessible(aContent, aDoc),
35       mNativeObject(nil),
36       mNativeInited(false) {
37   if (aContent && aContent->IsElement() && aDoc) {
38     // Check if this accessible is a live region and queue it
39     // it for dispatching an event after it has been inserted.
40     DocAccessibleWrap* doc = static_cast<DocAccessibleWrap*>(aDoc);
41     static const dom::Element::AttrValuesArray sLiveRegionValues[] = {
42         nsGkAtoms::OFF, nsGkAtoms::polite, nsGkAtoms::assertive, nullptr};
43     int32_t attrValue = nsAccUtils::FindARIAAttrValueIn(
44         aContent->AsElement(), nsGkAtoms::aria_live, sLiveRegionValues,
45         eIgnoreCase);
46     if (attrValue == 0) {
47       // aria-live is "off", do nothing.
48     } else if (attrValue > 0) {
49       // aria-live attribute is polite or assertive. It's live!
50       doc->QueueNewLiveRegion(this);
51     } else if (const nsRoleMapEntry* roleMap =
52                    aria::GetRoleMap(aContent->AsElement())) {
53       // aria role defines it as a live region. It's live!
54       if (roleMap->liveAttRule == ePoliteLiveAttr ||
55           roleMap->liveAttRule == eAssertiveLiveAttr) {
56         doc->QueueNewLiveRegion(this);
57       }
58     } else if (nsStaticAtom* value = GetAccService()->MarkupAttribute(
59                    aContent, nsGkAtoms::aria_live)) {
60       // HTML element defines it as a live region. It's live!
61       if (value == nsGkAtoms::polite || value == nsGkAtoms::assertive) {
62         doc->QueueNewLiveRegion(this);
63       }
64     }
65   }
68 AccessibleWrap::~AccessibleWrap() {}
70 mozAccessible* AccessibleWrap::GetNativeObject() {
71   NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
73   if (!mNativeInited && !mNativeObject) {
74     // We don't creat OSX accessibles for xul tooltips, defunct accessibles,
75     // <br> (whitespace) elements, or pruned children.
76     //
77     // To maintain a scripting environment where the XPCOM accessible hierarchy
78     // look the same on all platforms, we still let the C++ objects be created
79     // though.
80     if (!IsXULTooltip() && !IsDefunct() && Role() != roles::WHITESPACE) {
81       mNativeObject = [[GetNativeType() alloc] initWithAccessible:this];
82     }
83   }
85   mNativeInited = true;
87   return mNativeObject;
89   NS_OBJC_END_TRY_BLOCK_RETURN(nil);
92 void AccessibleWrap::GetNativeInterface(void** aOutInterface) {
93   *aOutInterface = static_cast<void*>(GetNativeObject());
96 // overridden in subclasses to create the right kind of object. by default we
97 // create a generic 'mozAccessible' node.
98 Class AccessibleWrap::GetNativeType() {
99   NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
101   if (IsXULTabpanels()) {
102     return [mozPaneAccessible class];
103   }
105   if (IsTable()) {
106     return [mozTableAccessible class];
107   }
109   if (IsTableRow()) {
110     return [mozTableRowAccessible class];
111   }
113   if (IsTableCell()) {
114     return [mozTableCellAccessible class];
115   }
117   if (IsDoc()) {
118     return [MOXWebAreaAccessible class];
119   }
121   return GetTypeFromRole(Role());
123   NS_OBJC_END_TRY_BLOCK_RETURN(nil);
126 // this method is very important. it is fired when an accessible object "dies".
127 // after this point the object might still be around (because some 3rd party
128 // still has a ref to it), but it is in fact 'dead'.
129 void AccessibleWrap::Shutdown() {
130   // this ensure we will not try to re-create the native object.
131   mNativeInited = true;
133   // we really intend to access the member directly.
134   if (mNativeObject) {
135     [mNativeObject expire];
136     [mNativeObject release];
137     mNativeObject = nil;
138   }
140   LocalAccessible::Shutdown();
143 nsresult AccessibleWrap::HandleAccEvent(AccEvent* aEvent) {
144   NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
146   nsresult rv = LocalAccessible::HandleAccEvent(aEvent);
147   NS_ENSURE_SUCCESS(rv, rv);
149   if (IsDefunct()) {
150     // The accessible can become defunct after their events are handled.
151     return NS_OK;
152   }
154   uint32_t eventType = aEvent->GetEventType();
156   if (eventType == nsIAccessibleEvent::EVENT_SHOW) {
157     DocAccessibleWrap* doc = static_cast<DocAccessibleWrap*>(Document());
158     doc->ProcessNewLiveRegions();
159   }
161   return NS_OK;
163   NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE);
166 ////////////////////////////////////////////////////////////////////////////////
167 // AccessibleWrap protected
169 Class a11y::GetTypeFromRole(roles::Role aRole) {
170   NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
172   switch (aRole) {
173     case roles::COMBOBOX:
174       return [mozPopupButtonAccessible class];
176     case roles::PUSHBUTTON:
177       return [mozButtonAccessible class];
179     case roles::PAGETAB:
180       return [mozTabAccessible class];
182     case roles::DATE_EDITOR:
183       return [mozDatePickerAccessible class];
185     case roles::CHECKBUTTON:
186     case roles::TOGGLE_BUTTON:
187     case roles::SWITCH:
188     case roles::CHECK_MENU_ITEM:
189       return [mozCheckboxAccessible class];
191     case roles::RADIOBUTTON:
192     case roles::RADIO_MENU_ITEM:
193       return [mozRadioButtonAccessible class];
195     case roles::SPINBUTTON:
196     case roles::SLIDER:
197       return [mozIncrementableAccessible class];
199     case roles::HEADING:
200       return [mozHeadingAccessible class];
202     case roles::PAGETABLIST:
203       return [mozTabGroupAccessible class];
205     case roles::ENTRY:
206     case roles::CAPTION:
207     case roles::EDITCOMBOBOX:
208     case roles::PASSWORD_TEXT:
209       // normal textfield (static or editable)
210       return [mozTextAccessible class];
212     case roles::TEXT_LEAF:
213     case roles::STATICTEXT:
214       return [mozTextLeafAccessible class];
216     case roles::LANDMARK:
217       return [MOXLandmarkAccessible class];
219     case roles::LINK:
220       return [mozLinkAccessible class];
222     case roles::LISTBOX:
223       return [mozListboxAccessible class];
225     case roles::LISTITEM:
226       return [MOXListItemAccessible class];
228     case roles::OPTION: {
229       return [mozOptionAccessible class];
230     }
232     case roles::RICH_OPTION: {
233       return [mozSelectableChildAccessible class];
234     }
236     case roles::COMBOBOX_LIST:
237     case roles::MENUBAR:
238     case roles::MENUPOPUP: {
239       return [mozMenuAccessible class];
240     }
242     case roles::COMBOBOX_OPTION:
243     case roles::PARENT_MENUITEM:
244     case roles::MENUITEM: {
245       return [mozMenuItemAccessible class];
246     }
248     case roles::MATHML_ROOT:
249       return [MOXMathRootAccessible class];
251     case roles::MATHML_SQUARE_ROOT:
252       return [MOXMathSquareRootAccessible class];
254     case roles::MATHML_FRACTION:
255       return [MOXMathFractionAccessible class];
257     case roles::MATHML_SUB:
258     case roles::MATHML_SUP:
259     case roles::MATHML_SUB_SUP:
260       return [MOXMathSubSupAccessible class];
262     case roles::MATHML_UNDER:
263     case roles::MATHML_OVER:
264     case roles::MATHML_UNDER_OVER:
265       return [MOXMathUnderOverAccessible class];
267     case roles::OUTLINE:
268     case roles::TREE_TABLE:
269       return [mozOutlineAccessible class];
271     case roles::OUTLINEITEM:
272       return [mozOutlineRowAccessible class];
274     default:
275       return [mozAccessible class];
276   }
278   return nil;
280   NS_OBJC_END_TRY_BLOCK_RETURN(nil);