accessible/src/base/NotificationController.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #ifndef mozilla_a11y_NotificationController_h_
michael@0 7 #define mozilla_a11y_NotificationController_h_
michael@0 8
michael@0 9 #include "EventQueue.h"
michael@0 10
michael@0 11 #include "nsCycleCollectionParticipant.h"
michael@0 12 #include "nsRefreshDriver.h"
michael@0 13
michael@0 14 #ifdef A11Y_LOG
michael@0 15 #include "Logging.h"
michael@0 16 #endif
michael@0 17
michael@0 18 namespace mozilla {
michael@0 19 namespace a11y {
michael@0 20
michael@0 21 class DocAccessible;
michael@0 22
michael@0 23 /**
michael@0 24 * Notification interface.
michael@0 25 */
michael@0 26 class Notification
michael@0 27 {
michael@0 28 public:
michael@0 29 NS_INLINE_DECL_REFCOUNTING(Notification)
michael@0 30
michael@0 31 /**
michael@0 32 * Process notification.
michael@0 33 */
michael@0 34 virtual void Process() = 0;
michael@0 35
michael@0 36 protected:
michael@0 37 Notification() { }
michael@0 38
michael@0 39 /**
michael@0 40 * Protected destructor, to discourage deletion outside of Release():
michael@0 41 */
michael@0 42 virtual ~Notification() { }
michael@0 43
michael@0 44 private:
michael@0 45 Notification(const Notification&);
michael@0 46 Notification& operator = (const Notification&);
michael@0 47 };
michael@0 48
michael@0 49
michael@0 50 /**
michael@0 51 * Template class for generic notification.
michael@0 52 *
michael@0 53 * @note Instance is kept as a weak ref, the caller must guarantee it exists
michael@0 54 * longer than the document accessible owning the notification controller
michael@0 55 * that this notification is processed by.
michael@0 56 */
michael@0 57 template<class Class, class Arg>
michael@0 58 class TNotification : public Notification
michael@0 59 {
michael@0 60 public:
michael@0 61 typedef void (Class::*Callback)(Arg*);
michael@0 62
michael@0 63 TNotification(Class* aInstance, Callback aCallback, Arg* aArg) :
michael@0 64 mInstance(aInstance), mCallback(aCallback), mArg(aArg) { }
michael@0 65 virtual ~TNotification() { mInstance = nullptr; }
michael@0 66
michael@0 67 virtual void Process()
michael@0 68 {
michael@0 69 (mInstance->*mCallback)(mArg);
michael@0 70
michael@0 71 mInstance = nullptr;
michael@0 72 mCallback = nullptr;
michael@0 73 mArg = nullptr;
michael@0 74 }
michael@0 75
michael@0 76 private:
michael@0 77 TNotification(const TNotification&);
michael@0 78 TNotification& operator = (const TNotification&);
michael@0 79
michael@0 80 Class* mInstance;
michael@0 81 Callback mCallback;
michael@0 82 nsRefPtr<Arg> mArg;
michael@0 83 };
michael@0 84
michael@0 85 /**
michael@0 86 * Used to process notifications from core for the document accessible.
michael@0 87 */
michael@0 88 class NotificationController : public EventQueue,
michael@0 89 public nsARefreshObserver
michael@0 90 {
michael@0 91 public:
michael@0 92 NotificationController(DocAccessible* aDocument, nsIPresShell* aPresShell);
michael@0 93 virtual ~NotificationController();
michael@0 94
michael@0 95 NS_IMETHOD_(MozExternalRefCountType) AddRef(void);
michael@0 96 NS_IMETHOD_(MozExternalRefCountType) Release(void);
michael@0 97
michael@0 98 NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(NotificationController)
michael@0 99
michael@0 100 /**
michael@0 101 * Shutdown the notification controller.
michael@0 102 */
michael@0 103 void Shutdown();
michael@0 104
michael@0 105 /**
michael@0 106 * Put an accessible event into the queue to process it later.
michael@0 107 */
michael@0 108 void QueueEvent(AccEvent* aEvent)
michael@0 109 {
michael@0 110 if (PushEvent(aEvent))
michael@0 111 ScheduleProcessing();
michael@0 112 }
michael@0 113
michael@0 114 /**
michael@0 115 * Schedule binding the child document to the tree of this document.
michael@0 116 */
michael@0 117 void ScheduleChildDocBinding(DocAccessible* aDocument);
michael@0 118
michael@0 119 /**
michael@0 120 * Schedule the accessible tree update because of rendered text changes.
michael@0 121 */
michael@0 122 inline void ScheduleTextUpdate(nsIContent* aTextNode)
michael@0 123 {
michael@0 124 if (mTextHash.PutEntry(aTextNode))
michael@0 125 ScheduleProcessing();
michael@0 126 }
michael@0 127
michael@0 128 /**
michael@0 129 * Pend accessible tree update for content insertion.
michael@0 130 */
michael@0 131 void ScheduleContentInsertion(Accessible* aContainer,
michael@0 132 nsIContent* aStartChildNode,
michael@0 133 nsIContent* aEndChildNode);
michael@0 134
michael@0 135 /**
michael@0 136 * Process the generic notification synchronously if there are no pending
michael@0 137 * layout changes and no notifications are pending or being processed right
michael@0 138 * now. Otherwise, queue it up to process asynchronously.
michael@0 139 *
michael@0 140 * @note The caller must guarantee that the given instance still exists when
michael@0 141 * the notification is processed.
michael@0 142 */
michael@0 143 template<class Class, class Arg>
michael@0 144 inline void HandleNotification(Class* aInstance,
michael@0 145 typename TNotification<Class, Arg>::Callback aMethod,
michael@0 146 Arg* aArg)
michael@0 147 {
michael@0 148 if (!IsUpdatePending()) {
michael@0 149 #ifdef A11Y_LOG
michael@0 150 if (mozilla::a11y::logging::IsEnabled(mozilla::a11y::logging::eNotifications))
michael@0 151 mozilla::a11y::logging::Text("sync notification processing");
michael@0 152 #endif
michael@0 153 (aInstance->*aMethod)(aArg);
michael@0 154 return;
michael@0 155 }
michael@0 156
michael@0 157 nsRefPtr<Notification> notification =
michael@0 158 new TNotification<Class, Arg>(aInstance, aMethod, aArg);
michael@0 159 if (notification && mNotifications.AppendElement(notification))
michael@0 160 ScheduleProcessing();
michael@0 161 }
michael@0 162
michael@0 163 /**
michael@0 164 * Schedule the generic notification to process asynchronously.
michael@0 165 *
michael@0 166 * @note The caller must guarantee that the given instance still exists when
michael@0 167 * the notification is processed.
michael@0 168 */
michael@0 169 template<class Class, class Arg>
michael@0 170 inline void ScheduleNotification(Class* aInstance,
michael@0 171 typename TNotification<Class, Arg>::Callback aMethod,
michael@0 172 Arg* aArg)
michael@0 173 {
michael@0 174 nsRefPtr<Notification> notification =
michael@0 175 new TNotification<Class, Arg>(aInstance, aMethod, aArg);
michael@0 176 if (notification && mNotifications.AppendElement(notification))
michael@0 177 ScheduleProcessing();
michael@0 178 }
michael@0 179
michael@0 180 #ifdef DEBUG
michael@0 181 bool IsUpdating() const
michael@0 182 { return mObservingState == eRefreshProcessingForUpdate; }
michael@0 183 #endif
michael@0 184
michael@0 185 protected:
michael@0 186 nsCycleCollectingAutoRefCnt mRefCnt;
michael@0 187 NS_DECL_OWNINGTHREAD
michael@0 188
michael@0 189 /**
michael@0 190 * Start to observe refresh to make notifications and events processing after
michael@0 191 * layout.
michael@0 192 */
michael@0 193 void ScheduleProcessing();
michael@0 194
michael@0 195 /**
michael@0 196 * Return true if the accessible tree state update is pending.
michael@0 197 */
michael@0 198 bool IsUpdatePending();
michael@0 199
michael@0 200 private:
michael@0 201 NotificationController(const NotificationController&);
michael@0 202 NotificationController& operator = (const NotificationController&);
michael@0 203
michael@0 204 // nsARefreshObserver
michael@0 205 virtual void WillRefresh(mozilla::TimeStamp aTime);
michael@0 206
michael@0 207 private:
michael@0 208 /**
michael@0 209 * Indicates whether we're waiting on an event queue processing from our
michael@0 210 * notification controller to flush events.
michael@0 211 */
michael@0 212 enum eObservingState {
michael@0 213 eNotObservingRefresh,
michael@0 214 eRefreshObserving,
michael@0 215 eRefreshProcessing,
michael@0 216 eRefreshProcessingForUpdate
michael@0 217 };
michael@0 218 eObservingState mObservingState;
michael@0 219
michael@0 220 /**
michael@0 221 * The presshell of the document accessible.
michael@0 222 */
michael@0 223 nsIPresShell* mPresShell;
michael@0 224
michael@0 225 /**
michael@0 226 * Child documents that needs to be bound to the tree.
michael@0 227 */
michael@0 228 nsTArray<nsRefPtr<DocAccessible> > mHangingChildDocuments;
michael@0 229
michael@0 230 /**
michael@0 231 * Storage for content inserted notification information.
michael@0 232 */
michael@0 233 class ContentInsertion
michael@0 234 {
michael@0 235 public:
michael@0 236 ContentInsertion(DocAccessible* aDocument, Accessible* aContainer);
michael@0 237 virtual ~ContentInsertion() { mDocument = nullptr; }
michael@0 238
michael@0 239 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(ContentInsertion)
michael@0 240 NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(ContentInsertion)
michael@0 241
michael@0 242 bool InitChildList(nsIContent* aStartChildNode, nsIContent* aEndChildNode);
michael@0 243 void Process();
michael@0 244
michael@0 245 private:
michael@0 246 ContentInsertion();
michael@0 247 ContentInsertion(const ContentInsertion&);
michael@0 248 ContentInsertion& operator = (const ContentInsertion&);
michael@0 249
michael@0 250 // The document used to process content insertion, matched to document of
michael@0 251 // the notification controller that this notification belongs to, therefore
michael@0 252 // it's ok to keep it as weak ref.
michael@0 253 DocAccessible* mDocument;
michael@0 254
michael@0 255 // The container accessible that content insertion occurs within.
michael@0 256 nsRefPtr<Accessible> mContainer;
michael@0 257
michael@0 258 // Array of inserted contents.
michael@0 259 nsTArray<nsCOMPtr<nsIContent> > mInsertedContent;
michael@0 260 };
michael@0 261
michael@0 262 /**
michael@0 263 * A pending accessible tree update notifications for content insertions.
michael@0 264 * Don't make this an nsAutoTArray; we use SwapElements() on it.
michael@0 265 */
michael@0 266 nsTArray<nsRefPtr<ContentInsertion> > mContentInsertions;
michael@0 267
michael@0 268 template<class T>
michael@0 269 class nsCOMPtrHashKey : public PLDHashEntryHdr
michael@0 270 {
michael@0 271 public:
michael@0 272 typedef T* KeyType;
michael@0 273 typedef const T* KeyTypePointer;
michael@0 274
michael@0 275 nsCOMPtrHashKey(const T* aKey) : mKey(const_cast<T*>(aKey)) {}
michael@0 276 nsCOMPtrHashKey(const nsPtrHashKey<T> &aToCopy) : mKey(aToCopy.mKey) {}
michael@0 277 ~nsCOMPtrHashKey() { }
michael@0 278
michael@0 279 KeyType GetKey() const { return mKey; }
michael@0 280 bool KeyEquals(KeyTypePointer aKey) const { return aKey == mKey; }
michael@0 281
michael@0 282 static KeyTypePointer KeyToPointer(KeyType aKey) { return aKey; }
michael@0 283 static PLDHashNumber HashKey(KeyTypePointer aKey)
michael@0 284 { return NS_PTR_TO_INT32(aKey) >> 2; }
michael@0 285
michael@0 286 enum { ALLOW_MEMMOVE = true };
michael@0 287
michael@0 288 protected:
michael@0 289 nsCOMPtr<T> mKey;
michael@0 290 };
michael@0 291
michael@0 292 /**
michael@0 293 * A pending accessible tree update notifications for rendered text changes.
michael@0 294 */
michael@0 295 nsTHashtable<nsCOMPtrHashKey<nsIContent> > mTextHash;
michael@0 296
michael@0 297 /**
michael@0 298 * Update the accessible tree for pending rendered text change notifications.
michael@0 299 */
michael@0 300 static PLDHashOperator TextEnumerator(nsCOMPtrHashKey<nsIContent>* aEntry,
michael@0 301 void* aUserArg);
michael@0 302
michael@0 303 /**
michael@0 304 * Other notifications like DOM events. Don't make this an nsAutoTArray; we
michael@0 305 * use SwapElements() on it.
michael@0 306 */
michael@0 307 nsTArray<nsRefPtr<Notification> > mNotifications;
michael@0 308 };
michael@0 309
michael@0 310 } // namespace a11y
michael@0 311 } // namespace mozilla
michael@0 312
michael@0 313 #endif // mozilla_a11y_NotificationController_h_

mercurial