AccEvent.h (16323B)
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 80 uint32_t GetEventType() const { return mEventType; } 81 EEventRule GetEventRule() const { return mEventRule; } 82 bool IsFromUserInput() const { return mIsFromUserInput; } 83 EIsFromUserInput FromUserInput() const { 84 return static_cast<EIsFromUserInput>(mIsFromUserInput); 85 } 86 87 LocalAccessible* GetAccessible() const { return mAccessible; } 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 eObjectAttrChangedEvent, 106 eScrollingEvent, 107 eAnnouncementEvent, 108 }; 109 110 static const EventGroup kEventGroup = eGenericEvent; 111 virtual unsigned int GetEventGroups() const { return 1U << eGenericEvent; } 112 113 /** 114 * Reference counting and cycle collection. 115 */ 116 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AccEvent) 117 NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(AccEvent) 118 119 protected: 120 virtual ~AccEvent() {} 121 122 bool mIsFromUserInput; 123 uint32_t mEventType; 124 EEventRule mEventRule; 125 RefPtr<LocalAccessible> mAccessible; 126 127 friend class EventQueue; 128 friend class EventTree; 129 friend class ::nsEventShell; 130 friend class NotificationController; 131 }; 132 133 /** 134 * Accessible state change event. 135 */ 136 class AccStateChangeEvent : public AccEvent { 137 public: 138 AccStateChangeEvent(LocalAccessible* aAccessible, uint64_t aState, 139 bool aIsEnabled, 140 EIsFromUserInput aIsFromUserInput = eAutoDetect) 141 : AccEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible, 142 aIsFromUserInput, eCoalesceStateChange), 143 mState(aState), 144 mIsEnabled(aIsEnabled) {} 145 146 AccStateChangeEvent(LocalAccessible* aAccessible, uint64_t aState) 147 : AccEvent(::nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible, 148 eAutoDetect, eCoalesceStateChange), 149 mState(aState) { 150 mIsEnabled = (mAccessible->State() & mState) != 0; 151 } 152 153 // AccEvent 154 static const EventGroup kEventGroup = eStateChangeEvent; 155 virtual unsigned int GetEventGroups() const override { 156 return AccEvent::GetEventGroups() | (1U << eStateChangeEvent); 157 } 158 159 // AccStateChangeEvent 160 uint64_t GetState() const { return mState; } 161 bool IsStateEnabled() const { return mIsEnabled; } 162 163 private: 164 uint64_t mState; 165 bool mIsEnabled; 166 167 friend class EventQueue; 168 }; 169 170 /** 171 * Accessible text change event. 172 */ 173 class AccTextChangeEvent : public AccEvent { 174 public: 175 AccTextChangeEvent(LocalAccessible* aAccessible, int32_t aStart, 176 const nsAString& aModifiedText, bool aIsInserted, 177 EIsFromUserInput aIsFromUserInput = eAutoDetect); 178 179 // AccEvent 180 static const EventGroup kEventGroup = eTextChangeEvent; 181 virtual unsigned int GetEventGroups() const override { 182 return AccEvent::GetEventGroups() | (1U << eTextChangeEvent); 183 } 184 185 // AccTextChangeEvent 186 int32_t GetStartOffset() const { return mStart; } 187 uint32_t GetLength() const { return mModifiedText.Length(); } 188 bool IsTextInserted() const { return mIsInserted; } 189 void GetModifiedText(nsAString& aModifiedText) { 190 aModifiedText = mModifiedText; 191 } 192 const nsString& ModifiedText() const { return mModifiedText; } 193 194 private: 195 int32_t mStart; 196 bool mIsInserted; 197 nsString mModifiedText; 198 199 friend class EventTree; 200 friend class NotificationController; 201 }; 202 203 /** 204 * A base class for events related to tree mutation, either an AccMutation 205 * event, or an AccReorderEvent. 206 */ 207 class AccTreeMutationEvent : public AccEvent { 208 public: 209 AccTreeMutationEvent(uint32_t aEventType, LocalAccessible* aTarget) 210 : AccEvent(aEventType, aTarget, eAutoDetect, eCoalesceReorder), 211 mGeneration(0) {} 212 213 // Event 214 static const EventGroup kEventGroup = eTreeMutationEvent; 215 virtual unsigned int GetEventGroups() const override { 216 return AccEvent::GetEventGroups() | (1U << eTreeMutationEvent); 217 } 218 219 void SetNextEvent(AccTreeMutationEvent* aNext) { mNextEvent = aNext; } 220 void SetPrevEvent(AccTreeMutationEvent* aPrev) { mPrevEvent = aPrev; } 221 AccTreeMutationEvent* NextEvent() const { return mNextEvent; } 222 AccTreeMutationEvent* PrevEvent() const { return mPrevEvent; } 223 224 /** 225 * A sequence number to know when this event was fired. 226 */ 227 uint32_t EventGeneration() const { return mGeneration; } 228 void SetEventGeneration(uint32_t aGeneration) { mGeneration = aGeneration; } 229 230 private: 231 RefPtr<AccTreeMutationEvent> mNextEvent; 232 RefPtr<AccTreeMutationEvent> mPrevEvent; 233 uint32_t mGeneration; 234 }; 235 236 /** 237 * Base class for show and hide accessible events. 238 */ 239 class AccMutationEvent : public AccTreeMutationEvent { 240 public: 241 AccMutationEvent(uint32_t aEventType, LocalAccessible* aTarget) 242 : AccTreeMutationEvent(aEventType, aTarget) { 243 // Don't coalesce these since they are coalesced by reorder event. Coalesce 244 // contained text change events. 245 mParent = mAccessible->LocalParent(); 246 } 247 virtual ~AccMutationEvent() {} 248 249 // Event 250 static const EventGroup kEventGroup = eMutationEvent; 251 virtual unsigned int GetEventGroups() const override { 252 return AccTreeMutationEvent::GetEventGroups() | (1U << eMutationEvent); 253 } 254 255 // MutationEvent 256 bool IsShow() const { return mEventType == nsIAccessibleEvent::EVENT_SHOW; } 257 bool IsHide() const { return mEventType == nsIAccessibleEvent::EVENT_HIDE; } 258 259 LocalAccessible* LocalParent() const { return mParent; } 260 261 protected: 262 RefPtr<LocalAccessible> mParent; 263 RefPtr<AccTextChangeEvent> mTextChangeEvent; 264 265 friend class EventTree; 266 friend class NotificationController; 267 }; 268 269 /** 270 * Accessible hide event. 271 */ 272 class AccHideEvent : public AccMutationEvent { 273 public: 274 explicit AccHideEvent(LocalAccessible* aTarget, bool aNeedsShutdown = true); 275 276 // Event 277 static const EventGroup kEventGroup = eHideEvent; 278 virtual unsigned int GetEventGroups() const override { 279 return AccMutationEvent::GetEventGroups() | (1U << eHideEvent); 280 } 281 282 // AccHideEvent 283 LocalAccessible* TargetParent() const { return mParent; } 284 LocalAccessible* TargetNextSibling() const { return mNextSibling; } 285 LocalAccessible* TargetPrevSibling() const { return mPrevSibling; } 286 bool NeedsShutdown() const { return mNeedsShutdown; } 287 288 protected: 289 bool mNeedsShutdown; 290 RefPtr<LocalAccessible> mNextSibling; 291 RefPtr<LocalAccessible> mPrevSibling; 292 293 friend class EventTree; 294 friend class NotificationController; 295 }; 296 297 /** 298 * Accessible show event. 299 */ 300 class AccShowEvent : public AccMutationEvent { 301 public: 302 explicit AccShowEvent(LocalAccessible* aTarget) 303 : AccMutationEvent(::nsIAccessibleEvent::EVENT_SHOW, aTarget) {} 304 305 // Event 306 static const EventGroup kEventGroup = eShowEvent; 307 virtual unsigned int GetEventGroups() const override { 308 return AccMutationEvent::GetEventGroups() | (1U << eShowEvent); 309 } 310 }; 311 312 /** 313 * Class for reorder accessible event. Takes care about 314 */ 315 class AccReorderEvent : public AccTreeMutationEvent { 316 public: 317 explicit AccReorderEvent(LocalAccessible* aTarget) 318 : AccTreeMutationEvent(::nsIAccessibleEvent::EVENT_REORDER, aTarget) {} 319 virtual ~AccReorderEvent() {} 320 321 // Event 322 static const EventGroup kEventGroup = eReorderEvent; 323 virtual unsigned int GetEventGroups() const override { 324 return AccTreeMutationEvent::GetEventGroups() | (1U << eReorderEvent); 325 } 326 327 /* 328 * Make this an inner reorder event that is coalesced into 329 * a reorder event of an ancestor. 330 */ 331 void SetInner() { mEventType = ::nsIAccessibleEvent::EVENT_INNER_REORDER; } 332 }; 333 334 /** 335 * Accessible caret move event. 336 */ 337 class AccCaretMoveEvent : public AccEvent { 338 public: 339 AccCaretMoveEvent(LocalAccessible* aAccessible, int32_t aCaretOffset, 340 bool aIsSelectionCollapsed, bool aIsAtEndOfLine, 341 int32_t aGranularity, 342 EIsFromUserInput aIsFromUserInput = eAutoDetect) 343 : AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible, 344 aIsFromUserInput), 345 mCaretOffset(aCaretOffset), 346 mIsSelectionCollapsed(aIsSelectionCollapsed), 347 mIsAtEndOfLine(aIsAtEndOfLine), 348 mGranularity(aGranularity) {} 349 virtual ~AccCaretMoveEvent() {} 350 351 // AccEvent 352 static const EventGroup kEventGroup = eCaretMoveEvent; 353 virtual unsigned int GetEventGroups() const override { 354 return AccEvent::GetEventGroups() | (1U << eCaretMoveEvent); 355 } 356 357 // AccCaretMoveEvent 358 int32_t GetCaretOffset() const { return mCaretOffset; } 359 360 bool IsSelectionCollapsed() const { return mIsSelectionCollapsed; } 361 bool IsAtEndOfLine() { return mIsAtEndOfLine; } 362 363 int32_t GetGranularity() const { return mGranularity; } 364 365 private: 366 int32_t mCaretOffset; 367 368 bool mIsSelectionCollapsed; 369 bool mIsAtEndOfLine; 370 int32_t mGranularity; 371 }; 372 373 /** 374 * Accessible text selection change event. 375 */ 376 class AccTextSelChangeEvent : public AccEvent { 377 public: 378 AccTextSelChangeEvent(HyperTextAccessible* aTarget, 379 dom::Selection* aSelection, int32_t aReason, 380 int32_t aGranularity); 381 virtual ~AccTextSelChangeEvent(); 382 383 // AccEvent 384 static const EventGroup kEventGroup = eTextSelChangeEvent; 385 virtual unsigned int GetEventGroups() const override { 386 return AccEvent::GetEventGroups() | (1U << eTextSelChangeEvent); 387 } 388 389 // AccTextSelChangeEvent 390 391 /** 392 * Return true if the text selection change wasn't caused by pure caret move. 393 */ 394 bool IsCaretMoveOnly() const; 395 396 int32_t GetGranularity() const { return mGranularity; } 397 398 /** 399 * Return selection ranges in document/control. 400 */ 401 void SelectionRanges(nsTArray<a11y::TextRange>* aRanges) const; 402 403 private: 404 RefPtr<dom::Selection> mSel; 405 int32_t mReason; 406 int32_t mGranularity; 407 408 friend class EventQueue; 409 friend class SelectionManager; 410 }; 411 412 /** 413 * Accessible widget selection change event. 414 */ 415 class AccSelChangeEvent : public AccEvent { 416 public: 417 enum SelChangeType { eSelectionAdd, eSelectionRemove }; 418 419 AccSelChangeEvent(LocalAccessible* aWidget, LocalAccessible* aItem, 420 SelChangeType aSelChangeType); 421 422 virtual ~AccSelChangeEvent() {} 423 424 // AccEvent 425 static const EventGroup kEventGroup = eSelectionChangeEvent; 426 virtual unsigned int GetEventGroups() const override { 427 return AccEvent::GetEventGroups() | (1U << eSelectionChangeEvent); 428 } 429 430 // AccSelChangeEvent 431 LocalAccessible* Widget() const { return mWidget; } 432 433 private: 434 RefPtr<LocalAccessible> mWidget; 435 RefPtr<LocalAccessible> mItem; 436 SelChangeType mSelChangeType; 437 uint32_t mPreceedingCount; 438 AccSelChangeEvent* mPackedEvent; 439 440 friend class EventQueue; 441 }; 442 443 /** 444 * Accessible object attribute changed event. 445 */ 446 class AccObjectAttrChangedEvent : public AccEvent { 447 public: 448 AccObjectAttrChangedEvent(LocalAccessible* aAccessible, nsAtom* aAttribute) 449 : AccEvent(::nsIAccessibleEvent::EVENT_OBJECT_ATTRIBUTE_CHANGED, 450 aAccessible), 451 mAttribute(aAttribute) {} 452 453 // AccEvent 454 static const EventGroup kEventGroup = eObjectAttrChangedEvent; 455 virtual unsigned int GetEventGroups() const override { 456 return AccEvent::GetEventGroups() | (1U << eObjectAttrChangedEvent); 457 } 458 459 // AccObjectAttrChangedEvent 460 nsAtom* GetAttribute() const { return mAttribute; } 461 462 private: 463 RefPtr<nsAtom> mAttribute; 464 465 virtual ~AccObjectAttrChangedEvent() {} 466 }; 467 468 /** 469 * Accessible scroll event. 470 */ 471 class AccScrollingEvent : public AccEvent { 472 public: 473 AccScrollingEvent(uint32_t aEventType, LocalAccessible* aAccessible, 474 uint32_t aScrollX, uint32_t aScrollY, uint32_t aMaxScrollX, 475 uint32_t aMaxScrollY) 476 : AccEvent(aEventType, aAccessible), 477 mScrollX(aScrollX), 478 mScrollY(aScrollY), 479 mMaxScrollX(aMaxScrollX), 480 mMaxScrollY(aMaxScrollY) {} 481 482 virtual ~AccScrollingEvent() {} 483 484 // AccEvent 485 static const EventGroup kEventGroup = eScrollingEvent; 486 virtual unsigned int GetEventGroups() const override { 487 return AccEvent::GetEventGroups() | (1U << eScrollingEvent); 488 } 489 490 // The X scrolling offset of the container when the event was fired. 491 uint32_t ScrollX() { return mScrollX; } 492 // The Y scrolling offset of the container when the event was fired. 493 uint32_t ScrollY() { return mScrollY; } 494 // The max X offset of the container. 495 uint32_t MaxScrollX() { return mMaxScrollX; } 496 // The max Y offset of the container. 497 uint32_t MaxScrollY() { return mMaxScrollY; } 498 499 private: 500 uint32_t mScrollX; 501 uint32_t mScrollY; 502 uint32_t mMaxScrollX; 503 uint32_t mMaxScrollY; 504 }; 505 506 /** 507 * Accessible announcement event. 508 */ 509 class AccAnnouncementEvent : public AccEvent { 510 public: 511 AccAnnouncementEvent(LocalAccessible* aAccessible, 512 const nsAString& aAnnouncement, uint16_t aPriority) 513 : AccEvent(nsIAccessibleEvent::EVENT_ANNOUNCEMENT, aAccessible), 514 mAnnouncement(aAnnouncement), 515 mPriority(aPriority) {} 516 517 virtual ~AccAnnouncementEvent() {} 518 519 // AccEvent 520 static const EventGroup kEventGroup = eAnnouncementEvent; 521 virtual unsigned int GetEventGroups() const override { 522 return AccEvent::GetEventGroups() | (1U << eAnnouncementEvent); 523 } 524 525 const nsString& Announcement() const { return mAnnouncement; } 526 527 uint16_t Priority() { return mPriority; } 528 529 private: 530 nsString mAnnouncement; 531 uint16_t mPriority; 532 }; 533 534 /** 535 * Downcast the generic accessible event object to derived type. 536 */ 537 class downcast_accEvent { 538 public: 539 explicit downcast_accEvent(AccEvent* e) : mRawPtr(e) {} 540 541 template <class Destination> 542 operator Destination*() { 543 if (!mRawPtr) return nullptr; 544 545 return mRawPtr->GetEventGroups() & (1U << Destination::kEventGroup) 546 ? static_cast<Destination*>(mRawPtr) 547 : nullptr; 548 } 549 550 private: 551 AccEvent* mRawPtr; 552 }; 553 554 /** 555 * Return a new xpcom accessible event for the given internal one. 556 */ 557 already_AddRefed<nsIAccessibleEvent> MakeXPCEvent(AccEvent* aEvent); 558 559 } // namespace a11y 560 } // namespace mozilla 561 562 #endif