Bug 1874684 - Part 28: Return DateDuration from DifferenceISODateTime. r=mgaudet
[gecko.git] / accessible / base / AccEvent.cpp
blob1d1b4386f8bb9b4a14c7c08c4b31f667820c1aee
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "AccEvent.h"
9 #include "nsAccUtils.h"
10 #include "xpcAccEvents.h"
11 #include "States.h"
12 #include "TextRange.h"
13 #include "xpcAccessibleDocument.h"
14 #include "xpcAccessibleTextRange.h"
16 #include "mozilla/dom/Selection.h"
17 #include "mozilla/dom/UserActivation.h"
19 #include "nsComponentManagerUtils.h"
20 #include "nsIMutableArray.h"
22 using namespace mozilla;
23 using namespace mozilla::a11y;
25 static_assert(static_cast<bool>(eNoUserInput) == false &&
26 static_cast<bool>(eFromUserInput) == true,
27 "EIsFromUserInput cannot be casted to bool");
29 ////////////////////////////////////////////////////////////////////////////////
30 // AccEvent
31 ////////////////////////////////////////////////////////////////////////////////
33 ////////////////////////////////////////////////////////////////////////////////
34 // AccEvent constructors
36 AccEvent::AccEvent(uint32_t aEventType, LocalAccessible* aAccessible,
37 EIsFromUserInput aIsFromUserInput, EEventRule aEventRule)
38 : mEventType(aEventType), mEventRule(aEventRule), mAccessible(aAccessible) {
39 if (aIsFromUserInput == eAutoDetect) {
40 mIsFromUserInput = dom::UserActivation::IsHandlingUserInput();
41 } else {
42 mIsFromUserInput = aIsFromUserInput == eFromUserInput ? true : false;
46 ////////////////////////////////////////////////////////////////////////////////
47 // AccEvent cycle collection
49 NS_IMPL_CYCLE_COLLECTION_CLASS(AccEvent)
51 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AccEvent)
52 NS_IMPL_CYCLE_COLLECTION_UNLINK(mAccessible)
53 if (AccTreeMutationEvent* tmEvent = downcast_accEvent(tmp)) {
54 tmEvent->SetNextEvent(nullptr);
55 tmEvent->SetPrevEvent(nullptr);
57 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
59 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AccEvent)
60 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAccessible)
61 if (AccTreeMutationEvent* tmEvent = downcast_accEvent(tmp)) {
62 CycleCollectionNoteChild(cb, tmEvent->NextEvent(), "mNext");
63 CycleCollectionNoteChild(cb, tmEvent->PrevEvent(), "mPrevEvent");
65 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
67 ////////////////////////////////////////////////////////////////////////////////
68 ////////////////////////////////////////////////////////////////////////////////
69 // AccTextChangeEvent
70 ////////////////////////////////////////////////////////////////////////////////
72 // Note: we pass in eAllowDupes to the base class because we don't support text
73 // events coalescence. We fire delayed text change events in DocAccessible but
74 // we continue to base the event off the accessible object rather than just the
75 // node. This means we won't try to create an accessible based on the node when
76 // we are ready to fire the event and so we will no longer assert at that point
77 // if the node was removed from the document. Either way, the AT won't work with
78 // a defunct accessible so the behaviour should be equivalent.
79 AccTextChangeEvent::AccTextChangeEvent(LocalAccessible* aAccessible,
80 int32_t aStart,
81 const nsAString& aModifiedText,
82 bool aIsInserted,
83 EIsFromUserInput aIsFromUserInput)
84 : AccEvent(
85 aIsInserted
86 ? static_cast<uint32_t>(nsIAccessibleEvent::EVENT_TEXT_INSERTED)
87 : static_cast<uint32_t>(nsIAccessibleEvent::EVENT_TEXT_REMOVED),
88 aAccessible, aIsFromUserInput, eAllowDupes),
89 mStart(aStart),
90 mIsInserted(aIsInserted),
91 mModifiedText(aModifiedText) {
92 // XXX We should use IsFromUserInput here, but that isn't always correct
93 // when the text change isn't related to content insertion or removal.
94 mIsFromUserInput =
95 mAccessible->State() & (states::FOCUSED | states::EDITABLE);
98 ////////////////////////////////////////////////////////////////////////////////
99 // AccHideEvent
100 ////////////////////////////////////////////////////////////////////////////////
102 AccHideEvent::AccHideEvent(LocalAccessible* aTarget, bool aNeedsShutdown)
103 : AccMutationEvent(::nsIAccessibleEvent::EVENT_HIDE, aTarget),
104 mNeedsShutdown(aNeedsShutdown) {
105 mNextSibling = mAccessible->LocalNextSibling();
106 mPrevSibling = mAccessible->LocalPrevSibling();
109 ////////////////////////////////////////////////////////////////////////////////
110 // AccShowEvent
111 ////////////////////////////////////////////////////////////////////////////////
113 ////////////////////////////////////////////////////////////////////////////////
114 // AccTextSelChangeEvent
115 ////////////////////////////////////////////////////////////////////////////////
117 AccTextSelChangeEvent::AccTextSelChangeEvent(HyperTextAccessible* aTarget,
118 dom::Selection* aSelection,
119 int32_t aReason,
120 int32_t aGranularity)
121 : AccEvent(nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED, aTarget,
122 eAutoDetect, eCoalesceTextSelChange),
123 mSel(aSelection),
124 mReason(aReason),
125 mGranularity(aGranularity) {}
127 AccTextSelChangeEvent::~AccTextSelChangeEvent() {}
129 bool AccTextSelChangeEvent::IsCaretMoveOnly() const {
130 return mSel->RangeCount() == 1 && mSel->IsCollapsed() &&
131 ((mReason & (nsISelectionListener::COLLAPSETOSTART_REASON |
132 nsISelectionListener::COLLAPSETOEND_REASON)) == 0);
135 void AccTextSelChangeEvent::SelectionRanges(
136 nsTArray<TextRange>* aRanges) const {
137 TextRange::TextRangesFromSelection(mSel, aRanges);
140 ////////////////////////////////////////////////////////////////////////////////
141 // AccSelChangeEvent
142 ////////////////////////////////////////////////////////////////////////////////
144 AccSelChangeEvent::AccSelChangeEvent(LocalAccessible* aWidget,
145 LocalAccessible* aItem,
146 SelChangeType aSelChangeType)
147 : AccEvent(0, aItem, eAutoDetect, eCoalesceSelectionChange),
148 mWidget(aWidget),
149 mItem(aItem),
150 mSelChangeType(aSelChangeType),
151 mPreceedingCount(0),
152 mPackedEvent(nullptr) {
153 if (aSelChangeType == eSelectionAdd) {
154 if (mWidget->GetSelectedItem(1)) {
155 mEventType = nsIAccessibleEvent::EVENT_SELECTION_ADD;
156 } else {
157 mEventType = nsIAccessibleEvent::EVENT_SELECTION;
159 } else {
160 mEventType = nsIAccessibleEvent::EVENT_SELECTION_REMOVE;
164 already_AddRefed<nsIAccessibleEvent> a11y::MakeXPCEvent(AccEvent* aEvent) {
165 DocAccessible* doc = aEvent->Document();
166 LocalAccessible* acc = aEvent->GetAccessible();
167 nsINode* node = acc->GetNode();
168 bool fromUser = aEvent->IsFromUserInput();
169 uint32_t type = aEvent->GetEventType();
170 uint32_t eventGroup = aEvent->GetEventGroups();
171 nsCOMPtr<nsIAccessibleEvent> xpEvent;
173 if (eventGroup & (1 << AccEvent::eStateChangeEvent)) {
174 AccStateChangeEvent* sc = downcast_accEvent(aEvent);
175 bool extra = false;
176 uint32_t state = nsAccUtils::To32States(sc->GetState(), &extra);
177 xpEvent = new xpcAccStateChangeEvent(type, ToXPC(acc), ToXPCDocument(doc),
178 node, fromUser, state, extra,
179 sc->IsStateEnabled());
180 return xpEvent.forget();
183 if (eventGroup & (1 << AccEvent::eTextChangeEvent)) {
184 AccTextChangeEvent* tc = downcast_accEvent(aEvent);
185 nsString text;
186 tc->GetModifiedText(text);
187 xpEvent = new xpcAccTextChangeEvent(
188 type, ToXPC(acc), ToXPCDocument(doc), node, fromUser,
189 tc->GetStartOffset(), tc->GetLength(), tc->IsTextInserted(), text);
190 return xpEvent.forget();
193 if (eventGroup & (1 << AccEvent::eHideEvent)) {
194 AccHideEvent* hideEvent = downcast_accEvent(aEvent);
195 xpEvent = new xpcAccHideEvent(type, ToXPC(acc), ToXPCDocument(doc), node,
196 fromUser, ToXPC(hideEvent->TargetParent()),
197 ToXPC(hideEvent->TargetNextSibling()),
198 ToXPC(hideEvent->TargetPrevSibling()));
199 return xpEvent.forget();
202 if (eventGroup & (1 << AccEvent::eCaretMoveEvent)) {
203 AccCaretMoveEvent* cm = downcast_accEvent(aEvent);
204 xpEvent = new xpcAccCaretMoveEvent(
205 type, ToXPC(acc), ToXPCDocument(doc), node, fromUser,
206 cm->GetCaretOffset(), cm->IsSelectionCollapsed(), cm->IsAtEndOfLine(),
207 cm->GetGranularity());
208 return xpEvent.forget();
211 if (eventGroup & (1 << AccEvent::eTextSelChangeEvent)) {
212 AccTextSelChangeEvent* tsc = downcast_accEvent(aEvent);
213 AutoTArray<TextRange, 1> ranges;
214 tsc->SelectionRanges(&ranges);
216 nsCOMPtr<nsIMutableArray> xpcRanges =
217 do_CreateInstance(NS_ARRAY_CONTRACTID);
218 uint32_t len = ranges.Length();
219 for (uint32_t idx = 0; idx < len; idx++) {
220 xpcRanges->AppendElement(new xpcAccessibleTextRange(ranges[idx]));
223 xpEvent = new xpcAccTextSelectionChangeEvent(
224 type, ToXPC(acc), ToXPCDocument(doc), node, fromUser, xpcRanges);
225 return xpEvent.forget();
228 if (eventGroup & (1 << AccEvent::eObjectAttrChangedEvent)) {
229 AccObjectAttrChangedEvent* oac = downcast_accEvent(aEvent);
230 nsString attribute;
231 oac->GetAttribute()->ToString(attribute);
232 xpEvent = new xpcAccObjectAttributeChangedEvent(
233 type, ToXPC(acc), ToXPCDocument(doc), node, fromUser, attribute);
234 return xpEvent.forget();
237 if (eventGroup & (1 << AccEvent::eScrollingEvent)) {
238 AccScrollingEvent* sa = downcast_accEvent(aEvent);
239 xpEvent = new xpcAccScrollingEvent(
240 type, ToXPC(acc), ToXPCDocument(doc), node, fromUser, sa->ScrollX(),
241 sa->ScrollY(), sa->MaxScrollX(), sa->MaxScrollY());
242 return xpEvent.forget();
245 if (eventGroup & (1 << AccEvent::eAnnouncementEvent)) {
246 AccAnnouncementEvent* aa = downcast_accEvent(aEvent);
247 xpEvent = new xpcAccAnnouncementEvent(type, ToXPC(acc), ToXPCDocument(doc),
248 node, fromUser, aa->Announcement(),
249 aa->Priority());
250 return xpEvent.forget();
253 xpEvent =
254 new xpcAccEvent(type, ToXPC(acc), ToXPCDocument(doc), node, fromUser);
255 return xpEvent.forget();