1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/accessible/src/base/AccEvent.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,526 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef _AccEvent_H_ 1.10 +#define _AccEvent_H_ 1.11 + 1.12 +#include "nsIAccessibleEvent.h" 1.13 + 1.14 +#include "mozilla/a11y/Accessible.h" 1.15 + 1.16 +namespace mozilla { 1.17 + 1.18 +namespace dom { 1.19 +class Selection; 1.20 +} 1.21 + 1.22 +namespace a11y { 1.23 + 1.24 +class DocAccessible; 1.25 + 1.26 +// Constants used to point whether the event is from user input. 1.27 +enum EIsFromUserInput 1.28 +{ 1.29 + // eNoUserInput: event is not from user input 1.30 + eNoUserInput = 0, 1.31 + // eFromUserInput: event is from user input 1.32 + eFromUserInput = 1, 1.33 + // eAutoDetect: the value should be obtained from event state manager 1.34 + eAutoDetect = -1 1.35 +}; 1.36 + 1.37 +/** 1.38 + * Generic accessible event. 1.39 + */ 1.40 +class AccEvent 1.41 +{ 1.42 +public: 1.43 + 1.44 + // Rule for accessible events. 1.45 + // The rule will be applied when flushing pending events. 1.46 + enum EEventRule { 1.47 + // eAllowDupes : More than one event of the same type is allowed. 1.48 + // This event will always be emitted. This flag is used for events that 1.49 + // don't support coalescence. 1.50 + eAllowDupes, 1.51 + 1.52 + // eCoalesceReorder : For reorder events from the same subtree or the same 1.53 + // node, only the umbrella event on the ancestor will be emitted. 1.54 + eCoalesceReorder, 1.55 + 1.56 + // eCoalesceMutationTextChange : coalesce text change events caused by 1.57 + // tree mutations of the same tree level. 1.58 + eCoalesceMutationTextChange, 1.59 + 1.60 + // eCoalesceOfSameType : For events of the same type, only the newest event 1.61 + // will be processed. 1.62 + eCoalesceOfSameType, 1.63 + 1.64 + // eCoalesceSelectionChange: coalescence of selection change events. 1.65 + eCoalesceSelectionChange, 1.66 + 1.67 + // eCoalesceStateChange: coalesce state change events. 1.68 + eCoalesceStateChange, 1.69 + 1.70 + // eCoalesceTextSelChange: coalescence of text selection change events. 1.71 + eCoalesceTextSelChange, 1.72 + 1.73 + // eRemoveDupes : For repeat events, only the newest event in queue 1.74 + // will be emitted. 1.75 + eRemoveDupes, 1.76 + 1.77 + // eDoNotEmit : This event is confirmed as a duplicate, do not emit it. 1.78 + eDoNotEmit 1.79 + }; 1.80 + 1.81 + // Initialize with an nsIAccessible 1.82 + AccEvent(uint32_t aEventType, Accessible* aAccessible, 1.83 + EIsFromUserInput aIsFromUserInput = eAutoDetect, 1.84 + EEventRule aEventRule = eRemoveDupes); 1.85 + virtual ~AccEvent() {} 1.86 + 1.87 + // AccEvent 1.88 + uint32_t GetEventType() const { return mEventType; } 1.89 + EEventRule GetEventRule() const { return mEventRule; } 1.90 + bool IsFromUserInput() const { return mIsFromUserInput; } 1.91 + EIsFromUserInput FromUserInput() const 1.92 + { return static_cast<EIsFromUserInput>(mIsFromUserInput); } 1.93 + 1.94 + Accessible* GetAccessible() const { return mAccessible; } 1.95 + DocAccessible* GetDocAccessible() const { return mAccessible->Document(); } 1.96 + 1.97 + /** 1.98 + * Down casting. 1.99 + */ 1.100 + enum EventGroup { 1.101 + eGenericEvent, 1.102 + eStateChangeEvent, 1.103 + eTextChangeEvent, 1.104 + eMutationEvent, 1.105 + eReorderEvent, 1.106 + eHideEvent, 1.107 + eShowEvent, 1.108 + eCaretMoveEvent, 1.109 + eTextSelChangeEvent, 1.110 + eSelectionChangeEvent, 1.111 + eTableChangeEvent, 1.112 + eVirtualCursorChangeEvent 1.113 + }; 1.114 + 1.115 + static const EventGroup kEventGroup = eGenericEvent; 1.116 + virtual unsigned int GetEventGroups() const 1.117 + { 1.118 + return 1U << eGenericEvent; 1.119 + } 1.120 + 1.121 + /** 1.122 + * Reference counting and cycle collection. 1.123 + */ 1.124 + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AccEvent) 1.125 + NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(AccEvent) 1.126 + 1.127 +protected: 1.128 + bool mIsFromUserInput; 1.129 + uint32_t mEventType; 1.130 + EEventRule mEventRule; 1.131 + nsRefPtr<Accessible> mAccessible; 1.132 + 1.133 + friend class EventQueue; 1.134 + friend class AccReorderEvent; 1.135 +}; 1.136 + 1.137 + 1.138 +/** 1.139 + * Accessible state change event. 1.140 + */ 1.141 +class AccStateChangeEvent: public AccEvent 1.142 +{ 1.143 +public: 1.144 + AccStateChangeEvent(Accessible* aAccessible, uint64_t aState, 1.145 + bool aIsEnabled, 1.146 + EIsFromUserInput aIsFromUserInput = eAutoDetect) : 1.147 + AccEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible, 1.148 + aIsFromUserInput, eCoalesceStateChange), 1.149 + mState(aState), mIsEnabled(aIsEnabled) { } 1.150 + 1.151 + AccStateChangeEvent(Accessible* aAccessible, uint64_t aState) : 1.152 + AccEvent(::nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible, 1.153 + eAutoDetect, eCoalesceStateChange), mState(aState) 1.154 + { mIsEnabled = (mAccessible->State() & mState) != 0; } 1.155 + 1.156 + // AccEvent 1.157 + static const EventGroup kEventGroup = eStateChangeEvent; 1.158 + virtual unsigned int GetEventGroups() const 1.159 + { 1.160 + return AccEvent::GetEventGroups() | (1U << eStateChangeEvent); 1.161 + } 1.162 + 1.163 + // AccStateChangeEvent 1.164 + uint64_t GetState() const { return mState; } 1.165 + bool IsStateEnabled() const { return mIsEnabled; } 1.166 + 1.167 +private: 1.168 + uint64_t mState; 1.169 + bool mIsEnabled; 1.170 + 1.171 + friend class EventQueue; 1.172 +}; 1.173 + 1.174 + 1.175 +/** 1.176 + * Accessible text change event. 1.177 + */ 1.178 +class AccTextChangeEvent: public AccEvent 1.179 +{ 1.180 +public: 1.181 + AccTextChangeEvent(Accessible* aAccessible, int32_t aStart, 1.182 + const nsAString& aModifiedText, bool aIsInserted, 1.183 + EIsFromUserInput aIsFromUserInput = eAutoDetect); 1.184 + 1.185 + // AccEvent 1.186 + static const EventGroup kEventGroup = eTextChangeEvent; 1.187 + virtual unsigned int GetEventGroups() const 1.188 + { 1.189 + return AccEvent::GetEventGroups() | (1U << eTextChangeEvent); 1.190 + } 1.191 + 1.192 + // AccTextChangeEvent 1.193 + int32_t GetStartOffset() const { return mStart; } 1.194 + uint32_t GetLength() const { return mModifiedText.Length(); } 1.195 + bool IsTextInserted() const { return mIsInserted; } 1.196 + void GetModifiedText(nsAString& aModifiedText) 1.197 + { aModifiedText = mModifiedText; } 1.198 + 1.199 +private: 1.200 + int32_t mStart; 1.201 + bool mIsInserted; 1.202 + nsString mModifiedText; 1.203 + 1.204 + friend class EventQueue; 1.205 + friend class AccReorderEvent; 1.206 +}; 1.207 + 1.208 + 1.209 +/** 1.210 + * Base class for show and hide accessible events. 1.211 + */ 1.212 +class AccMutationEvent: public AccEvent 1.213 +{ 1.214 +public: 1.215 + AccMutationEvent(uint32_t aEventType, Accessible* aTarget, 1.216 + nsINode* aTargetNode) : 1.217 + AccEvent(aEventType, aTarget, eAutoDetect, eCoalesceMutationTextChange) 1.218 + { 1.219 + // Don't coalesce these since they are coalesced by reorder event. Coalesce 1.220 + // contained text change events. 1.221 + mParent = mAccessible->Parent(); 1.222 + } 1.223 + virtual ~AccMutationEvent() { } 1.224 + 1.225 + // Event 1.226 + static const EventGroup kEventGroup = eMutationEvent; 1.227 + virtual unsigned int GetEventGroups() const 1.228 + { 1.229 + return AccEvent::GetEventGroups() | (1U << eMutationEvent); 1.230 + } 1.231 + 1.232 + // MutationEvent 1.233 + bool IsShow() const { return mEventType == nsIAccessibleEvent::EVENT_SHOW; } 1.234 + bool IsHide() const { return mEventType == nsIAccessibleEvent::EVENT_HIDE; } 1.235 + 1.236 +protected: 1.237 + nsCOMPtr<nsINode> mNode; 1.238 + nsRefPtr<Accessible> mParent; 1.239 + nsRefPtr<AccTextChangeEvent> mTextChangeEvent; 1.240 + 1.241 + friend class EventQueue; 1.242 +}; 1.243 + 1.244 + 1.245 +/** 1.246 + * Accessible hide event. 1.247 + */ 1.248 +class AccHideEvent: public AccMutationEvent 1.249 +{ 1.250 +public: 1.251 + AccHideEvent(Accessible* aTarget, nsINode* aTargetNode); 1.252 + 1.253 + // Event 1.254 + static const EventGroup kEventGroup = eHideEvent; 1.255 + virtual unsigned int GetEventGroups() const 1.256 + { 1.257 + return AccMutationEvent::GetEventGroups() | (1U << eHideEvent); 1.258 + } 1.259 + 1.260 + // AccHideEvent 1.261 + Accessible* TargetParent() const { return mParent; } 1.262 + Accessible* TargetNextSibling() const { return mNextSibling; } 1.263 + Accessible* TargetPrevSibling() const { return mPrevSibling; } 1.264 + 1.265 +protected: 1.266 + nsRefPtr<Accessible> mNextSibling; 1.267 + nsRefPtr<Accessible> mPrevSibling; 1.268 + 1.269 + friend class EventQueue; 1.270 +}; 1.271 + 1.272 + 1.273 +/** 1.274 + * Accessible show event. 1.275 + */ 1.276 +class AccShowEvent: public AccMutationEvent 1.277 +{ 1.278 +public: 1.279 + AccShowEvent(Accessible* aTarget, nsINode* aTargetNode); 1.280 + 1.281 + // Event 1.282 + static const EventGroup kEventGroup = eShowEvent; 1.283 + virtual unsigned int GetEventGroups() const 1.284 + { 1.285 + return AccMutationEvent::GetEventGroups() | (1U << eShowEvent); 1.286 + } 1.287 +}; 1.288 + 1.289 + 1.290 +/** 1.291 + * Class for reorder accessible event. Takes care about 1.292 + */ 1.293 +class AccReorderEvent : public AccEvent 1.294 +{ 1.295 +public: 1.296 + AccReorderEvent(Accessible* aTarget) : 1.297 + AccEvent(::nsIAccessibleEvent::EVENT_REORDER, aTarget, 1.298 + eAutoDetect, eCoalesceReorder) { } 1.299 + virtual ~AccReorderEvent() { } 1.300 + 1.301 + // Event 1.302 + static const EventGroup kEventGroup = eReorderEvent; 1.303 + virtual unsigned int GetEventGroups() const 1.304 + { 1.305 + return AccEvent::GetEventGroups() | (1U << eReorderEvent); 1.306 + } 1.307 + 1.308 + /** 1.309 + * Get connected with mutation event. 1.310 + */ 1.311 + void AddSubMutationEvent(AccMutationEvent* aEvent) 1.312 + { mDependentEvents.AppendElement(aEvent); } 1.313 + 1.314 + /** 1.315 + * Do not emit the reorder event and its connected mutation events. 1.316 + */ 1.317 + void DoNotEmitAll() 1.318 + { 1.319 + mEventRule = AccEvent::eDoNotEmit; 1.320 + uint32_t eventsCount = mDependentEvents.Length(); 1.321 + for (uint32_t idx = 0; idx < eventsCount; idx++) 1.322 + mDependentEvents[idx]->mEventRule = AccEvent::eDoNotEmit; 1.323 + } 1.324 + 1.325 + /** 1.326 + * Return true if the given accessible is a target of connected mutation 1.327 + * event. 1.328 + */ 1.329 + uint32_t IsShowHideEventTarget(const Accessible* aTarget) const; 1.330 + 1.331 +protected: 1.332 + /** 1.333 + * Show and hide events causing this reorder event. 1.334 + */ 1.335 + nsTArray<AccMutationEvent*> mDependentEvents; 1.336 + 1.337 + friend class EventQueue; 1.338 +}; 1.339 + 1.340 + 1.341 +/** 1.342 + * Accessible caret move event. 1.343 + */ 1.344 +class AccCaretMoveEvent: public AccEvent 1.345 +{ 1.346 +public: 1.347 + AccCaretMoveEvent(Accessible* aAccessible, int32_t aCaretOffset, 1.348 + EIsFromUserInput aIsFromUserInput = eAutoDetect) : 1.349 + AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible, 1.350 + aIsFromUserInput), 1.351 + mCaretOffset(aCaretOffset) { } 1.352 + virtual ~AccCaretMoveEvent() { } 1.353 + 1.354 + // AccEvent 1.355 + static const EventGroup kEventGroup = eCaretMoveEvent; 1.356 + virtual unsigned int GetEventGroups() const 1.357 + { 1.358 + return AccEvent::GetEventGroups() | (1U << eCaretMoveEvent); 1.359 + } 1.360 + 1.361 + // AccCaretMoveEvent 1.362 + int32_t GetCaretOffset() const { return mCaretOffset; } 1.363 + 1.364 +private: 1.365 + int32_t mCaretOffset; 1.366 +}; 1.367 + 1.368 + 1.369 +/** 1.370 + * Accessible text selection change event. 1.371 + */ 1.372 +class AccTextSelChangeEvent : public AccEvent 1.373 +{ 1.374 +public: 1.375 + AccTextSelChangeEvent(HyperTextAccessible* aTarget, 1.376 + dom::Selection* aSelection, 1.377 + int32_t aReason); 1.378 + virtual ~AccTextSelChangeEvent(); 1.379 + 1.380 + // AccEvent 1.381 + static const EventGroup kEventGroup = eTextSelChangeEvent; 1.382 + virtual unsigned int GetEventGroups() const 1.383 + { 1.384 + return AccEvent::GetEventGroups() | (1U << eTextSelChangeEvent); 1.385 + } 1.386 + 1.387 + // AccTextSelChangeEvent 1.388 + 1.389 + /** 1.390 + * Return true if the text selection change wasn't caused by pure caret move. 1.391 + */ 1.392 + bool IsCaretMoveOnly() const; 1.393 + 1.394 +private: 1.395 + nsRefPtr<dom::Selection> mSel; 1.396 + int32_t mReason; 1.397 + 1.398 + friend class EventQueue; 1.399 + friend class SelectionManager; 1.400 +}; 1.401 + 1.402 + 1.403 +/** 1.404 + * Accessible widget selection change event. 1.405 + */ 1.406 +class AccSelChangeEvent : public AccEvent 1.407 +{ 1.408 +public: 1.409 + enum SelChangeType { 1.410 + eSelectionAdd, 1.411 + eSelectionRemove 1.412 + }; 1.413 + 1.414 + AccSelChangeEvent(Accessible* aWidget, Accessible* aItem, 1.415 + SelChangeType aSelChangeType); 1.416 + 1.417 + virtual ~AccSelChangeEvent() { } 1.418 + 1.419 + // AccEvent 1.420 + static const EventGroup kEventGroup = eSelectionChangeEvent; 1.421 + virtual unsigned int GetEventGroups() const 1.422 + { 1.423 + return AccEvent::GetEventGroups() | (1U << eSelectionChangeEvent); 1.424 + } 1.425 + 1.426 + // AccSelChangeEvent 1.427 + Accessible* Widget() const { return mWidget; } 1.428 + 1.429 +private: 1.430 + nsRefPtr<Accessible> mWidget; 1.431 + nsRefPtr<Accessible> mItem; 1.432 + SelChangeType mSelChangeType; 1.433 + uint32_t mPreceedingCount; 1.434 + AccSelChangeEvent* mPackedEvent; 1.435 + 1.436 + friend class EventQueue; 1.437 +}; 1.438 + 1.439 + 1.440 +/** 1.441 + * Accessible table change event. 1.442 + */ 1.443 +class AccTableChangeEvent : public AccEvent 1.444 +{ 1.445 +public: 1.446 + AccTableChangeEvent(Accessible* aAccessible, uint32_t aEventType, 1.447 + int32_t aRowOrColIndex, int32_t aNumRowsOrCols); 1.448 + 1.449 + // AccEvent 1.450 + static const EventGroup kEventGroup = eTableChangeEvent; 1.451 + virtual unsigned int GetEventGroups() const 1.452 + { 1.453 + return AccEvent::GetEventGroups() | (1U << eTableChangeEvent); 1.454 + } 1.455 + 1.456 + // AccTableChangeEvent 1.457 + uint32_t GetIndex() const { return mRowOrColIndex; } 1.458 + uint32_t GetCount() const { return mNumRowsOrCols; } 1.459 + 1.460 +private: 1.461 + uint32_t mRowOrColIndex; // the start row/column after which the rows are inserted/deleted. 1.462 + uint32_t mNumRowsOrCols; // the number of inserted/deleted rows/columns 1.463 +}; 1.464 + 1.465 +/** 1.466 + * Accessible virtual cursor change event. 1.467 + */ 1.468 +class AccVCChangeEvent : public AccEvent 1.469 +{ 1.470 +public: 1.471 + AccVCChangeEvent(Accessible* aAccessible, 1.472 + nsIAccessible* aOldAccessible, 1.473 + int32_t aOldStart, int32_t aOldEnd, 1.474 + int16_t aReason); 1.475 + 1.476 + virtual ~AccVCChangeEvent() { } 1.477 + 1.478 + // AccEvent 1.479 + static const EventGroup kEventGroup = eVirtualCursorChangeEvent; 1.480 + virtual unsigned int GetEventGroups() const 1.481 + { 1.482 + return AccEvent::GetEventGroups() | (1U << eVirtualCursorChangeEvent); 1.483 + } 1.484 + 1.485 + // AccTableChangeEvent 1.486 + nsIAccessible* OldAccessible() const { return mOldAccessible; } 1.487 + int32_t OldStartOffset() const { return mOldStart; } 1.488 + int32_t OldEndOffset() const { return mOldEnd; } 1.489 + int32_t Reason() const { return mReason; } 1.490 + 1.491 +private: 1.492 + nsRefPtr<nsIAccessible> mOldAccessible; 1.493 + int32_t mOldStart; 1.494 + int32_t mOldEnd; 1.495 + int16_t mReason; 1.496 +}; 1.497 + 1.498 +/** 1.499 + * Downcast the generic accessible event object to derived type. 1.500 + */ 1.501 +class downcast_accEvent 1.502 +{ 1.503 +public: 1.504 + downcast_accEvent(AccEvent* e) : mRawPtr(e) { } 1.505 + 1.506 + template<class Destination> 1.507 + operator Destination*() { 1.508 + if (!mRawPtr) 1.509 + return nullptr; 1.510 + 1.511 + return mRawPtr->GetEventGroups() & (1U << Destination::kEventGroup) ? 1.512 + static_cast<Destination*>(mRawPtr) : nullptr; 1.513 + } 1.514 + 1.515 +private: 1.516 + AccEvent* mRawPtr; 1.517 +}; 1.518 + 1.519 +/** 1.520 + * Return a new xpcom accessible event for the given internal one. 1.521 + */ 1.522 +already_AddRefed<nsIAccessibleEvent> 1.523 +MakeXPCEvent(AccEvent* aEvent); 1.524 + 1.525 +} // namespace a11y 1.526 +} // namespace mozilla 1.527 + 1.528 +#endif 1.529 +