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