no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / accessible / mac / DocAccessibleWrap.mm
blob9b21251e1eea60b71cd596e9630d45166d99c109
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 "ARIAMap.h"
10 #include "DocAccessible-inl.h"
11 #include "nsAccUtils.h"
13 #import "mozAccessible.h"
14 #import "MOXTextMarkerDelegate.h"
16 using namespace mozilla;
17 using namespace mozilla::a11y;
19 DocAccessibleWrap::DocAccessibleWrap(dom::Document* aDocument,
20                                      PresShell* aPresShell)
21     : DocAccessible(aDocument, aPresShell) {}
23 void DocAccessibleWrap::Shutdown() {
24   [MOXTextMarkerDelegate destroyForDoc:this];
25   DocAccessible::Shutdown();
28 DocAccessibleWrap::~DocAccessibleWrap() {}
30 void DocAccessibleWrap::AttributeChanged(dom::Element* aElement,
31                                          int32_t aNameSpaceID,
32                                          nsAtom* aAttribute, int32_t aModType,
33                                          const nsAttrValue* aOldValue) {
34   DocAccessible::AttributeChanged(aElement, aNameSpaceID, aAttribute, aModType,
35                                   aOldValue);
36   if (aAttribute == nsGkAtoms::aria_live) {
37     LocalAccessible* accessible =
38         mContent != aElement ? GetAccessible(aElement) : this;
39     if (!accessible) {
40       return;
41     }
43     static const dom::Element::AttrValuesArray sLiveRegionValues[] = {
44         nsGkAtoms::OFF, nsGkAtoms::polite, nsGkAtoms::assertive, nullptr};
45     int32_t attrValue = nsAccUtils::FindARIAAttrValueIn(
46         aElement, nsGkAtoms::aria_live, sLiveRegionValues, eIgnoreCase);
47     if (attrValue > 0) {
48       if (!aOldValue || aOldValue->IsEmptyString() ||
49           aOldValue->Equals(nsGkAtoms::OFF, eIgnoreCase)) {
50         // This element just got an active aria-live attribute value
51         FireDelayedEvent(nsIAccessibleEvent::EVENT_LIVE_REGION_ADDED,
52                          accessible);
53       }
54     } else {
55       if (aOldValue && (aOldValue->Equals(nsGkAtoms::polite, eIgnoreCase) ||
56                         aOldValue->Equals(nsGkAtoms::assertive, eIgnoreCase))) {
57         // This element lost an active live region
58         FireDelayedEvent(nsIAccessibleEvent::EVENT_LIVE_REGION_REMOVED,
59                          accessible);
60       } else if (attrValue == 0) {
61         // aria-live="off", check if its a role-based live region that
62         // needs to be removed.
63         if (const nsRoleMapEntry* roleMap = accessible->ARIARoleMap()) {
64           // aria role defines it as a live region. It's live!
65           if (roleMap->liveAttRule == ePoliteLiveAttr ||
66               roleMap->liveAttRule == eAssertiveLiveAttr) {
67             FireDelayedEvent(nsIAccessibleEvent::EVENT_LIVE_REGION_REMOVED,
68                              accessible);
69           }
70         } else if (nsStaticAtom* value = GetAccService()->MarkupAttribute(
71                        aElement, nsGkAtoms::aria_live)) {
72           // HTML element defines it as a live region. It's live!
73           if (value == nsGkAtoms::polite || value == nsGkAtoms::assertive) {
74             FireDelayedEvent(nsIAccessibleEvent::EVENT_LIVE_REGION_REMOVED,
75                              accessible);
76           }
77         }
78       }
79     }
80   }
83 void DocAccessibleWrap::QueueNewLiveRegion(LocalAccessible* aAccessible) {
84   if (!aAccessible) {
85     return;
86   }
88   mNewLiveRegions.Insert(aAccessible->UniqueID());
91 void DocAccessibleWrap::ProcessNewLiveRegions() {
92   for (const auto& uniqueID : mNewLiveRegions) {
93     if (LocalAccessible* liveRegion =
94             GetAccessibleByUniqueID(const_cast<void*>(uniqueID))) {
95       FireDelayedEvent(nsIAccessibleEvent::EVENT_LIVE_REGION_ADDED, liveRegion);
96     }
97   }
99   mNewLiveRegions.Clear();
102 void DocAccessibleWrap::DoInitialUpdate() {
103   DocAccessible::DoInitialUpdate();
104   ProcessNewLiveRegions();