|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #ifndef _AccEvent_H_ |
|
7 #define _AccEvent_H_ |
|
8 |
|
9 #include "nsIAccessibleEvent.h" |
|
10 |
|
11 #include "mozilla/a11y/Accessible.h" |
|
12 |
|
13 namespace mozilla { |
|
14 |
|
15 namespace dom { |
|
16 class Selection; |
|
17 } |
|
18 |
|
19 namespace a11y { |
|
20 |
|
21 class DocAccessible; |
|
22 |
|
23 // Constants used to point whether the event is from user input. |
|
24 enum EIsFromUserInput |
|
25 { |
|
26 // eNoUserInput: event is not from user input |
|
27 eNoUserInput = 0, |
|
28 // eFromUserInput: event is from user input |
|
29 eFromUserInput = 1, |
|
30 // eAutoDetect: the value should be obtained from event state manager |
|
31 eAutoDetect = -1 |
|
32 }; |
|
33 |
|
34 /** |
|
35 * Generic accessible event. |
|
36 */ |
|
37 class AccEvent |
|
38 { |
|
39 public: |
|
40 |
|
41 // Rule for accessible events. |
|
42 // The rule will be applied when flushing pending events. |
|
43 enum EEventRule { |
|
44 // eAllowDupes : More than one event of the same type is allowed. |
|
45 // This event will always be emitted. This flag is used for events that |
|
46 // don't support coalescence. |
|
47 eAllowDupes, |
|
48 |
|
49 // eCoalesceReorder : For reorder events from the same subtree or the same |
|
50 // node, only the umbrella event on the ancestor will be emitted. |
|
51 eCoalesceReorder, |
|
52 |
|
53 // eCoalesceMutationTextChange : coalesce text change events caused by |
|
54 // tree mutations of the same tree level. |
|
55 eCoalesceMutationTextChange, |
|
56 |
|
57 // eCoalesceOfSameType : For events of the same type, only the newest event |
|
58 // will be processed. |
|
59 eCoalesceOfSameType, |
|
60 |
|
61 // eCoalesceSelectionChange: coalescence of selection change events. |
|
62 eCoalesceSelectionChange, |
|
63 |
|
64 // eCoalesceStateChange: coalesce state change events. |
|
65 eCoalesceStateChange, |
|
66 |
|
67 // eCoalesceTextSelChange: coalescence of text selection change events. |
|
68 eCoalesceTextSelChange, |
|
69 |
|
70 // eRemoveDupes : For repeat events, only the newest event in queue |
|
71 // will be emitted. |
|
72 eRemoveDupes, |
|
73 |
|
74 // eDoNotEmit : This event is confirmed as a duplicate, do not emit it. |
|
75 eDoNotEmit |
|
76 }; |
|
77 |
|
78 // Initialize with an nsIAccessible |
|
79 AccEvent(uint32_t aEventType, Accessible* aAccessible, |
|
80 EIsFromUserInput aIsFromUserInput = eAutoDetect, |
|
81 EEventRule aEventRule = eRemoveDupes); |
|
82 virtual ~AccEvent() {} |
|
83 |
|
84 // AccEvent |
|
85 uint32_t GetEventType() const { return mEventType; } |
|
86 EEventRule GetEventRule() const { return mEventRule; } |
|
87 bool IsFromUserInput() const { return mIsFromUserInput; } |
|
88 EIsFromUserInput FromUserInput() const |
|
89 { return static_cast<EIsFromUserInput>(mIsFromUserInput); } |
|
90 |
|
91 Accessible* GetAccessible() const { return mAccessible; } |
|
92 DocAccessible* GetDocAccessible() const { return mAccessible->Document(); } |
|
93 |
|
94 /** |
|
95 * Down casting. |
|
96 */ |
|
97 enum EventGroup { |
|
98 eGenericEvent, |
|
99 eStateChangeEvent, |
|
100 eTextChangeEvent, |
|
101 eMutationEvent, |
|
102 eReorderEvent, |
|
103 eHideEvent, |
|
104 eShowEvent, |
|
105 eCaretMoveEvent, |
|
106 eTextSelChangeEvent, |
|
107 eSelectionChangeEvent, |
|
108 eTableChangeEvent, |
|
109 eVirtualCursorChangeEvent |
|
110 }; |
|
111 |
|
112 static const EventGroup kEventGroup = eGenericEvent; |
|
113 virtual unsigned int GetEventGroups() const |
|
114 { |
|
115 return 1U << eGenericEvent; |
|
116 } |
|
117 |
|
118 /** |
|
119 * Reference counting and cycle collection. |
|
120 */ |
|
121 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AccEvent) |
|
122 NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(AccEvent) |
|
123 |
|
124 protected: |
|
125 bool mIsFromUserInput; |
|
126 uint32_t mEventType; |
|
127 EEventRule mEventRule; |
|
128 nsRefPtr<Accessible> mAccessible; |
|
129 |
|
130 friend class EventQueue; |
|
131 friend class AccReorderEvent; |
|
132 }; |
|
133 |
|
134 |
|
135 /** |
|
136 * Accessible state change event. |
|
137 */ |
|
138 class AccStateChangeEvent: public AccEvent |
|
139 { |
|
140 public: |
|
141 AccStateChangeEvent(Accessible* aAccessible, uint64_t aState, |
|
142 bool aIsEnabled, |
|
143 EIsFromUserInput aIsFromUserInput = eAutoDetect) : |
|
144 AccEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible, |
|
145 aIsFromUserInput, eCoalesceStateChange), |
|
146 mState(aState), mIsEnabled(aIsEnabled) { } |
|
147 |
|
148 AccStateChangeEvent(Accessible* aAccessible, uint64_t aState) : |
|
149 AccEvent(::nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible, |
|
150 eAutoDetect, eCoalesceStateChange), mState(aState) |
|
151 { mIsEnabled = (mAccessible->State() & mState) != 0; } |
|
152 |
|
153 // AccEvent |
|
154 static const EventGroup kEventGroup = eStateChangeEvent; |
|
155 virtual unsigned int GetEventGroups() const |
|
156 { |
|
157 return AccEvent::GetEventGroups() | (1U << eStateChangeEvent); |
|
158 } |
|
159 |
|
160 // AccStateChangeEvent |
|
161 uint64_t GetState() const { return mState; } |
|
162 bool IsStateEnabled() const { return mIsEnabled; } |
|
163 |
|
164 private: |
|
165 uint64_t mState; |
|
166 bool mIsEnabled; |
|
167 |
|
168 friend class EventQueue; |
|
169 }; |
|
170 |
|
171 |
|
172 /** |
|
173 * Accessible text change event. |
|
174 */ |
|
175 class AccTextChangeEvent: public AccEvent |
|
176 { |
|
177 public: |
|
178 AccTextChangeEvent(Accessible* aAccessible, int32_t aStart, |
|
179 const nsAString& aModifiedText, bool aIsInserted, |
|
180 EIsFromUserInput aIsFromUserInput = eAutoDetect); |
|
181 |
|
182 // AccEvent |
|
183 static const EventGroup kEventGroup = eTextChangeEvent; |
|
184 virtual unsigned int GetEventGroups() const |
|
185 { |
|
186 return AccEvent::GetEventGroups() | (1U << eTextChangeEvent); |
|
187 } |
|
188 |
|
189 // AccTextChangeEvent |
|
190 int32_t GetStartOffset() const { return mStart; } |
|
191 uint32_t GetLength() const { return mModifiedText.Length(); } |
|
192 bool IsTextInserted() const { return mIsInserted; } |
|
193 void GetModifiedText(nsAString& aModifiedText) |
|
194 { aModifiedText = mModifiedText; } |
|
195 |
|
196 private: |
|
197 int32_t mStart; |
|
198 bool mIsInserted; |
|
199 nsString mModifiedText; |
|
200 |
|
201 friend class EventQueue; |
|
202 friend class AccReorderEvent; |
|
203 }; |
|
204 |
|
205 |
|
206 /** |
|
207 * Base class for show and hide accessible events. |
|
208 */ |
|
209 class AccMutationEvent: public AccEvent |
|
210 { |
|
211 public: |
|
212 AccMutationEvent(uint32_t aEventType, Accessible* aTarget, |
|
213 nsINode* aTargetNode) : |
|
214 AccEvent(aEventType, aTarget, eAutoDetect, eCoalesceMutationTextChange) |
|
215 { |
|
216 // Don't coalesce these since they are coalesced by reorder event. Coalesce |
|
217 // contained text change events. |
|
218 mParent = mAccessible->Parent(); |
|
219 } |
|
220 virtual ~AccMutationEvent() { } |
|
221 |
|
222 // Event |
|
223 static const EventGroup kEventGroup = eMutationEvent; |
|
224 virtual unsigned int GetEventGroups() const |
|
225 { |
|
226 return AccEvent::GetEventGroups() | (1U << eMutationEvent); |
|
227 } |
|
228 |
|
229 // MutationEvent |
|
230 bool IsShow() const { return mEventType == nsIAccessibleEvent::EVENT_SHOW; } |
|
231 bool IsHide() const { return mEventType == nsIAccessibleEvent::EVENT_HIDE; } |
|
232 |
|
233 protected: |
|
234 nsCOMPtr<nsINode> mNode; |
|
235 nsRefPtr<Accessible> mParent; |
|
236 nsRefPtr<AccTextChangeEvent> mTextChangeEvent; |
|
237 |
|
238 friend class EventQueue; |
|
239 }; |
|
240 |
|
241 |
|
242 /** |
|
243 * Accessible hide event. |
|
244 */ |
|
245 class AccHideEvent: public AccMutationEvent |
|
246 { |
|
247 public: |
|
248 AccHideEvent(Accessible* aTarget, nsINode* aTargetNode); |
|
249 |
|
250 // Event |
|
251 static const EventGroup kEventGroup = eHideEvent; |
|
252 virtual unsigned int GetEventGroups() const |
|
253 { |
|
254 return AccMutationEvent::GetEventGroups() | (1U << eHideEvent); |
|
255 } |
|
256 |
|
257 // AccHideEvent |
|
258 Accessible* TargetParent() const { return mParent; } |
|
259 Accessible* TargetNextSibling() const { return mNextSibling; } |
|
260 Accessible* TargetPrevSibling() const { return mPrevSibling; } |
|
261 |
|
262 protected: |
|
263 nsRefPtr<Accessible> mNextSibling; |
|
264 nsRefPtr<Accessible> mPrevSibling; |
|
265 |
|
266 friend class EventQueue; |
|
267 }; |
|
268 |
|
269 |
|
270 /** |
|
271 * Accessible show event. |
|
272 */ |
|
273 class AccShowEvent: public AccMutationEvent |
|
274 { |
|
275 public: |
|
276 AccShowEvent(Accessible* aTarget, nsINode* aTargetNode); |
|
277 |
|
278 // Event |
|
279 static const EventGroup kEventGroup = eShowEvent; |
|
280 virtual unsigned int GetEventGroups() const |
|
281 { |
|
282 return AccMutationEvent::GetEventGroups() | (1U << eShowEvent); |
|
283 } |
|
284 }; |
|
285 |
|
286 |
|
287 /** |
|
288 * Class for reorder accessible event. Takes care about |
|
289 */ |
|
290 class AccReorderEvent : public AccEvent |
|
291 { |
|
292 public: |
|
293 AccReorderEvent(Accessible* aTarget) : |
|
294 AccEvent(::nsIAccessibleEvent::EVENT_REORDER, aTarget, |
|
295 eAutoDetect, eCoalesceReorder) { } |
|
296 virtual ~AccReorderEvent() { } |
|
297 |
|
298 // Event |
|
299 static const EventGroup kEventGroup = eReorderEvent; |
|
300 virtual unsigned int GetEventGroups() const |
|
301 { |
|
302 return AccEvent::GetEventGroups() | (1U << eReorderEvent); |
|
303 } |
|
304 |
|
305 /** |
|
306 * Get connected with mutation event. |
|
307 */ |
|
308 void AddSubMutationEvent(AccMutationEvent* aEvent) |
|
309 { mDependentEvents.AppendElement(aEvent); } |
|
310 |
|
311 /** |
|
312 * Do not emit the reorder event and its connected mutation events. |
|
313 */ |
|
314 void DoNotEmitAll() |
|
315 { |
|
316 mEventRule = AccEvent::eDoNotEmit; |
|
317 uint32_t eventsCount = mDependentEvents.Length(); |
|
318 for (uint32_t idx = 0; idx < eventsCount; idx++) |
|
319 mDependentEvents[idx]->mEventRule = AccEvent::eDoNotEmit; |
|
320 } |
|
321 |
|
322 /** |
|
323 * Return true if the given accessible is a target of connected mutation |
|
324 * event. |
|
325 */ |
|
326 uint32_t IsShowHideEventTarget(const Accessible* aTarget) const; |
|
327 |
|
328 protected: |
|
329 /** |
|
330 * Show and hide events causing this reorder event. |
|
331 */ |
|
332 nsTArray<AccMutationEvent*> mDependentEvents; |
|
333 |
|
334 friend class EventQueue; |
|
335 }; |
|
336 |
|
337 |
|
338 /** |
|
339 * Accessible caret move event. |
|
340 */ |
|
341 class AccCaretMoveEvent: public AccEvent |
|
342 { |
|
343 public: |
|
344 AccCaretMoveEvent(Accessible* aAccessible, int32_t aCaretOffset, |
|
345 EIsFromUserInput aIsFromUserInput = eAutoDetect) : |
|
346 AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible, |
|
347 aIsFromUserInput), |
|
348 mCaretOffset(aCaretOffset) { } |
|
349 virtual ~AccCaretMoveEvent() { } |
|
350 |
|
351 // AccEvent |
|
352 static const EventGroup kEventGroup = eCaretMoveEvent; |
|
353 virtual unsigned int GetEventGroups() const |
|
354 { |
|
355 return AccEvent::GetEventGroups() | (1U << eCaretMoveEvent); |
|
356 } |
|
357 |
|
358 // AccCaretMoveEvent |
|
359 int32_t GetCaretOffset() const { return mCaretOffset; } |
|
360 |
|
361 private: |
|
362 int32_t mCaretOffset; |
|
363 }; |
|
364 |
|
365 |
|
366 /** |
|
367 * Accessible text selection change event. |
|
368 */ |
|
369 class AccTextSelChangeEvent : public AccEvent |
|
370 { |
|
371 public: |
|
372 AccTextSelChangeEvent(HyperTextAccessible* aTarget, |
|
373 dom::Selection* aSelection, |
|
374 int32_t aReason); |
|
375 virtual ~AccTextSelChangeEvent(); |
|
376 |
|
377 // AccEvent |
|
378 static const EventGroup kEventGroup = eTextSelChangeEvent; |
|
379 virtual unsigned int GetEventGroups() const |
|
380 { |
|
381 return AccEvent::GetEventGroups() | (1U << eTextSelChangeEvent); |
|
382 } |
|
383 |
|
384 // AccTextSelChangeEvent |
|
385 |
|
386 /** |
|
387 * Return true if the text selection change wasn't caused by pure caret move. |
|
388 */ |
|
389 bool IsCaretMoveOnly() const; |
|
390 |
|
391 private: |
|
392 nsRefPtr<dom::Selection> mSel; |
|
393 int32_t mReason; |
|
394 |
|
395 friend class EventQueue; |
|
396 friend class SelectionManager; |
|
397 }; |
|
398 |
|
399 |
|
400 /** |
|
401 * Accessible widget selection change event. |
|
402 */ |
|
403 class AccSelChangeEvent : public AccEvent |
|
404 { |
|
405 public: |
|
406 enum SelChangeType { |
|
407 eSelectionAdd, |
|
408 eSelectionRemove |
|
409 }; |
|
410 |
|
411 AccSelChangeEvent(Accessible* aWidget, Accessible* aItem, |
|
412 SelChangeType aSelChangeType); |
|
413 |
|
414 virtual ~AccSelChangeEvent() { } |
|
415 |
|
416 // AccEvent |
|
417 static const EventGroup kEventGroup = eSelectionChangeEvent; |
|
418 virtual unsigned int GetEventGroups() const |
|
419 { |
|
420 return AccEvent::GetEventGroups() | (1U << eSelectionChangeEvent); |
|
421 } |
|
422 |
|
423 // AccSelChangeEvent |
|
424 Accessible* Widget() const { return mWidget; } |
|
425 |
|
426 private: |
|
427 nsRefPtr<Accessible> mWidget; |
|
428 nsRefPtr<Accessible> mItem; |
|
429 SelChangeType mSelChangeType; |
|
430 uint32_t mPreceedingCount; |
|
431 AccSelChangeEvent* mPackedEvent; |
|
432 |
|
433 friend class EventQueue; |
|
434 }; |
|
435 |
|
436 |
|
437 /** |
|
438 * Accessible table change event. |
|
439 */ |
|
440 class AccTableChangeEvent : public AccEvent |
|
441 { |
|
442 public: |
|
443 AccTableChangeEvent(Accessible* aAccessible, uint32_t aEventType, |
|
444 int32_t aRowOrColIndex, int32_t aNumRowsOrCols); |
|
445 |
|
446 // AccEvent |
|
447 static const EventGroup kEventGroup = eTableChangeEvent; |
|
448 virtual unsigned int GetEventGroups() const |
|
449 { |
|
450 return AccEvent::GetEventGroups() | (1U << eTableChangeEvent); |
|
451 } |
|
452 |
|
453 // AccTableChangeEvent |
|
454 uint32_t GetIndex() const { return mRowOrColIndex; } |
|
455 uint32_t GetCount() const { return mNumRowsOrCols; } |
|
456 |
|
457 private: |
|
458 uint32_t mRowOrColIndex; // the start row/column after which the rows are inserted/deleted. |
|
459 uint32_t mNumRowsOrCols; // the number of inserted/deleted rows/columns |
|
460 }; |
|
461 |
|
462 /** |
|
463 * Accessible virtual cursor change event. |
|
464 */ |
|
465 class AccVCChangeEvent : public AccEvent |
|
466 { |
|
467 public: |
|
468 AccVCChangeEvent(Accessible* aAccessible, |
|
469 nsIAccessible* aOldAccessible, |
|
470 int32_t aOldStart, int32_t aOldEnd, |
|
471 int16_t aReason); |
|
472 |
|
473 virtual ~AccVCChangeEvent() { } |
|
474 |
|
475 // AccEvent |
|
476 static const EventGroup kEventGroup = eVirtualCursorChangeEvent; |
|
477 virtual unsigned int GetEventGroups() const |
|
478 { |
|
479 return AccEvent::GetEventGroups() | (1U << eVirtualCursorChangeEvent); |
|
480 } |
|
481 |
|
482 // AccTableChangeEvent |
|
483 nsIAccessible* OldAccessible() const { return mOldAccessible; } |
|
484 int32_t OldStartOffset() const { return mOldStart; } |
|
485 int32_t OldEndOffset() const { return mOldEnd; } |
|
486 int32_t Reason() const { return mReason; } |
|
487 |
|
488 private: |
|
489 nsRefPtr<nsIAccessible> mOldAccessible; |
|
490 int32_t mOldStart; |
|
491 int32_t mOldEnd; |
|
492 int16_t mReason; |
|
493 }; |
|
494 |
|
495 /** |
|
496 * Downcast the generic accessible event object to derived type. |
|
497 */ |
|
498 class downcast_accEvent |
|
499 { |
|
500 public: |
|
501 downcast_accEvent(AccEvent* e) : mRawPtr(e) { } |
|
502 |
|
503 template<class Destination> |
|
504 operator Destination*() { |
|
505 if (!mRawPtr) |
|
506 return nullptr; |
|
507 |
|
508 return mRawPtr->GetEventGroups() & (1U << Destination::kEventGroup) ? |
|
509 static_cast<Destination*>(mRawPtr) : nullptr; |
|
510 } |
|
511 |
|
512 private: |
|
513 AccEvent* mRawPtr; |
|
514 }; |
|
515 |
|
516 /** |
|
517 * Return a new xpcom accessible event for the given internal one. |
|
518 */ |
|
519 already_AddRefed<nsIAccessibleEvent> |
|
520 MakeXPCEvent(AccEvent* aEvent); |
|
521 |
|
522 } // namespace a11y |
|
523 } // namespace mozilla |
|
524 |
|
525 #endif |
|
526 |