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