diff --git a/accessible/src/base/nsEventShell.cpp b/accessible/src/base/nsEventShell.cpp index d6beba6a58d9..90828984d27a 100644 --- a/accessible/src/base/nsEventShell.cpp +++ b/accessible/src/base/nsEventShell.cpp @@ -102,7 +102,7 @@ nsCOMPtr nsEventShell::sEventTargetNode; //////////////////////////////////////////////////////////////////////////////// nsAccEventQueue::nsAccEventQueue(nsDocAccessible *aDocument): - mProcessingStarted(PR_FALSE), mDocument(aDocument), mFlushingEventsCount(0) + mObservingRefresh(PR_FALSE), mDocument(aDocument) { } @@ -157,6 +157,13 @@ nsAccEventQueue::Push(nsAccEvent *aEvent) void nsAccEventQueue::Shutdown() { + if (mObservingRefresh) { + nsCOMPtr shell = mDocument->GetPresShell(); + if (!shell || + shell->RemoveRefreshObserver(this, Flush_Display)) { + mObservingRefresh = PR_FALSE; + } + } mDocument = nsnull; mEvents.Clear(); } @@ -169,14 +176,19 @@ nsAccEventQueue::PrepareFlush() { // If there are pending events in the queue and events flush isn't planed // yet start events flush asynchronously. - if (mEvents.Length() > 0 && !mProcessingStarted) { - NS_DISPATCH_RUNNABLEMETHOD(Flush, this) - mProcessingStarted = PR_TRUE; + if (mEvents.Length() > 0 && !mObservingRefresh) { + nsCOMPtr shell = mDocument->GetPresShell(); + // Use a Flush_Display observer so that it will get called after + // style and ayout have been flushed. + if (shell && + shell->AddRefreshObserver(this, Flush_Display)) { + mObservingRefresh = PR_TRUE; + } } } void -nsAccEventQueue::Flush() +nsAccEventQueue::WillRefresh(mozilla::TimeStamp aTime) { // If the document accessible is now shut down, don't fire events in it // anymore. @@ -187,20 +199,14 @@ nsAccEventQueue::Flush() if (!presShell) return; - // Flush layout so that all the frame construction, reflow, and styles are - // up-to-date. This will ensure we can get frames for the related nodes, as - // well as get the most current information for calculating things like - // visibility. We don't flush the display because we don't care about - // painting. If no flush is necessary the method will simple return. - presShell->FlushPendingNotifications(Flush_Layout); - // Process only currently queued events. Newly appended events during events // flushing won't be processed. - mFlushingEventsCount = mEvents.Length(); - NS_ASSERTION(mFlushingEventsCount, - "How did we get here without events to fire?"); + nsTArray < nsRefPtr > events; + events.SwapElements(mEvents); + PRUint32 length = events.Length(); + NS_ASSERTION(length, "How did we get here without events to fire?"); - for (PRUint32 index = 0; index < mFlushingEventsCount; index ++) { + for (PRUint32 index = 0; index < length; index ++) { // No presshell means the document was shut down during event handling // by AT. @@ -212,17 +218,12 @@ nsAccEventQueue::Flush() mDocument->ProcessPendingEvent(accEvent); } - // Mark we are ready to start event processing again. - mProcessingStarted = PR_FALSE; - - // If the document accessible is alive then remove processed events from the - // queue (otherwise they were removed on shutdown already) and reinitialize - // queue processing callback if necessary (new events might occur duiring - // delayed event processing). - if (mDocument && mDocument->HasWeakShell()) { - mEvents.RemoveElementsAt(0, mFlushingEventsCount); - mFlushingEventsCount = 0; - PrepareFlush(); + if (mEvents.Length() == 0) { + nsCOMPtr shell = mDocument->GetPresShell(); + if (!shell || + shell->RemoveRefreshObserver(this, Flush_Display)) { + mObservingRefresh = PR_FALSE; + } } } @@ -241,7 +242,7 @@ nsAccEventQueue::CoalesceEvents() switch(tailEvent->mEventRule) { case nsAccEvent::eCoalesceFromSameSubtree: { - for (PRInt32 index = tail - 1; index >= mFlushingEventsCount; index--) { + for (PRInt32 index = tail - 1; index >= 0; index--) { nsAccEvent* thisEvent = mEvents[index]; if (thisEvent->mEventType != tailEvent->mEventType) @@ -365,7 +366,7 @@ nsAccEventQueue::CoalesceEvents() // Do not emit thisEvent, also apply this result to sibling nodes of // thisNode. thisEvent->mEventRule = nsAccEvent::eDoNotEmit; - ApplyToSiblings(mFlushingEventsCount, index, thisEvent->mEventType, + ApplyToSiblings(0, index, thisEvent->mEventType, thisEvent->mNode, nsAccEvent::eDoNotEmit); continue; } @@ -386,7 +387,7 @@ nsAccEventQueue::CoalesceEvents() // Used for focus event, coalesce more older event since focus event // for accessible can be duplicated by event for its document, we are // interested in focus event for accessible. - for (PRInt32 index = tail - 1; index >= mFlushingEventsCount; index--) { + for (PRInt32 index = tail - 1; index >= 0; index--) { nsAccEvent* thisEvent = mEvents[index]; if (thisEvent->mEventType == tailEvent->mEventType && thisEvent->mEventRule == tailEvent->mEventRule && @@ -401,7 +402,7 @@ nsAccEventQueue::CoalesceEvents() { // Check for repeat events, coalesce newly appended event by more older // event. - for (PRInt32 index = tail - 1; index >= mFlushingEventsCount; index--) { + for (PRInt32 index = tail - 1; index >= 0; index--) { nsAccEvent* accEvent = mEvents[index]; if (accEvent->mEventType == tailEvent->mEventType && accEvent->mEventRule == tailEvent->mEventRule && diff --git a/accessible/src/base/nsEventShell.h b/accessible/src/base/nsEventShell.h index 7dbd74002b76..bab821ed621d 100644 --- a/accessible/src/base/nsEventShell.h +++ b/accessible/src/base/nsEventShell.h @@ -45,6 +45,8 @@ #include "nsAutoPtr.h" +#include "nsRefreshDriver.h" + class nsIPersistentProperties; /** @@ -90,7 +92,8 @@ private: /** * Event queue. */ -class nsAccEventQueue : public nsISupports +class nsAccEventQueue : public nsISupports, + public nsARefreshObserver { public: nsAccEventQueue(nsDocAccessible *aDocument); @@ -120,9 +123,7 @@ private: * Process pending events. It calls nsDocAccessible::ProcessPendingEvent() * where the real event processing is happen. */ - void Flush(); - - NS_DECL_RUNNABLEMETHOD(nsAccEventQueue, Flush) + virtual void WillRefresh(mozilla::TimeStamp aTime); /** * Coalesce redundant events from the queue. @@ -157,9 +158,10 @@ private: nsAccEvent *aDescendantAccEvent); /** - * Indicates whether events flush is run. + * Indicates whether we're waiting on a refresh notification from our + * presshell to flush events */ - PRBool mProcessingStarted; + PRBool mObservingRefresh; /** * The document accessible reference owning this queue. @@ -167,13 +169,8 @@ private: nsRefPtr mDocument; /** - * The number of events processed currently. Used to avoid event coalescence - * with new events appended to the queue because of events handling. - */ - PRInt32 mFlushingEventsCount; - - /** - * Pending events array. + * Pending events array. Don't make this an nsAutoTArray; we use + * SwapElements() on it. */ nsTArray > mEvents; };