зеркало из https://github.com/mozilla/gecko-dev.git
Bug 666446, Part 2/10 - Change nsRefreshDriver to accept imgIRequest objects to facilitate refresh driver-based animations. [r=roc]
This commit is contained in:
Родитель
d4b112def1
Коммит
81b7ddbeed
|
@ -114,6 +114,7 @@ nsRefreshDriver::nsRefreshDriver(nsPresContext *aPresContext)
|
|||
mTimerIsPrecise(false),
|
||||
mLastTimerInterval(0)
|
||||
{
|
||||
mRequests.Init();
|
||||
}
|
||||
|
||||
nsRefreshDriver::~nsRefreshDriver()
|
||||
|
@ -185,6 +186,29 @@ nsRefreshDriver::RemoveRefreshObserver(nsARefreshObserver *aObserver,
|
|||
return array.RemoveElement(aObserver);
|
||||
}
|
||||
|
||||
bool
|
||||
nsRefreshDriver::AddImageRequest(imgIRequest* aRequest)
|
||||
{
|
||||
if (!mRequests.PutEntry(aRequest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnsureTimerStarted(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsRefreshDriver::RemoveImageRequest(imgIRequest* aRequest)
|
||||
{
|
||||
mRequests.RemoveEntry(aRequest);
|
||||
}
|
||||
|
||||
void nsRefreshDriver::ClearAllImageRequests()
|
||||
{
|
||||
mRequests.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
nsRefreshDriver::EnsureTimerStarted(bool aAdjustingTimer)
|
||||
{
|
||||
|
@ -238,6 +262,7 @@ nsRefreshDriver::ObserverCount() const
|
|||
for (PRUint32 i = 0; i < ArrayLength(mObservers); ++i) {
|
||||
sum += mObservers[i].Length();
|
||||
}
|
||||
|
||||
// Even while throttled, we need to process layout and style changes. Style
|
||||
// changes can trigger transitions which fire events when they complete, and
|
||||
// layout changes can affect media queries on child documents, triggering
|
||||
|
@ -249,6 +274,12 @@ nsRefreshDriver::ObserverCount() const
|
|||
return sum;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsRefreshDriver::ImageRequestCount() const
|
||||
{
|
||||
return mRequests.Count();
|
||||
}
|
||||
|
||||
void
|
||||
nsRefreshDriver::UpdateMostRecentRefresh()
|
||||
{
|
||||
|
@ -303,7 +334,7 @@ nsRefreshDriver::Notify(nsITimer *aTimer)
|
|||
UpdateMostRecentRefresh();
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = mPresContext->GetPresShell();
|
||||
if (!presShell || ObserverCount() == 0) {
|
||||
if (!presShell || (ObserverCount() == 0 && ImageRequestCount() == 0)) {
|
||||
// Things are being destroyed, or we no longer have any observers.
|
||||
// We don't want to stop the timer when observers are initially
|
||||
// removed, because sometimes observers can be added and removed
|
||||
|
@ -332,6 +363,7 @@ nsRefreshDriver::Notify(nsITimer *aTimer)
|
|||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
// Don't just loop while we have things in mBeforePaintTargets,
|
||||
// the whole point is that event handlers should readd the
|
||||
|
@ -404,6 +436,17 @@ nsRefreshDriver::Notify(nsITimer *aTimer)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform notification to imgIRequests subscribed to listen
|
||||
* for refresh events.
|
||||
*/
|
||||
|
||||
ImageRequestParameters parms = {mMostRecentRefresh};
|
||||
if (mRequests.Count()) {
|
||||
mRequests.EnumerateEntries(nsRefreshDriver::ImageRequestEnumerator, &parms);
|
||||
EnsureTimerStarted(false);
|
||||
}
|
||||
|
||||
if (mThrottled ||
|
||||
(mTimerIsPrecise !=
|
||||
(GetRefreshTimerType() == nsITimer::TYPE_REPEATING_PRECISE_CAN_SKIP))) {
|
||||
|
@ -424,6 +467,24 @@ nsRefreshDriver::Notify(nsITimer *aTimer)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsRefreshDriver::ImageRequestEnumerator(nsISupportsHashKey* aEntry,
|
||||
void* aUserArg)
|
||||
{
|
||||
ImageRequestParameters* parms =
|
||||
static_cast<ImageRequestParameters*> (aUserArg);
|
||||
mozilla::TimeStamp mostRecentRefresh = parms->ts;
|
||||
imgIRequest* req = static_cast<imgIRequest*>(aEntry->GetKey());
|
||||
NS_ABORT_IF_FALSE(req, "Unable to retrieve the image request");
|
||||
nsCOMPtr<imgIContainer> image;
|
||||
req->GetImage(getter_AddRefs(image));
|
||||
if (image) {
|
||||
image->RequestRefresh(mostRecentRefresh);
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsRefreshDriver::Freeze()
|
||||
{
|
||||
|
@ -437,7 +498,7 @@ nsRefreshDriver::Thaw()
|
|||
{
|
||||
NS_ASSERTION(mFrozen, "Thaw called on an unfrozen refresh driver");
|
||||
mFrozen = false;
|
||||
if (ObserverCount()) {
|
||||
if (ObserverCount() || ImageRequestCount()) {
|
||||
// FIXME: This isn't quite right, since our EnsureTimerStarted call
|
||||
// updates our mMostRecentRefresh, but the DoRefresh call won't run
|
||||
// and notify our observers until we get back to the event loop.
|
||||
|
|
|
@ -50,10 +50,13 @@
|
|||
#include "nsTObserverArray.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
class nsPresContext;
|
||||
class nsIPresShell;
|
||||
class nsIDocument;
|
||||
class imgIRequest;
|
||||
|
||||
/**
|
||||
* An abstract base class to be implemented by callers wanting to be
|
||||
|
@ -128,6 +131,24 @@ public:
|
|||
bool RemoveRefreshObserver(nsARefreshObserver *aObserver,
|
||||
mozFlushType aFlushType);
|
||||
|
||||
/**
|
||||
* Add/Remove imgIRequest versions of observers.
|
||||
*
|
||||
* These are used for hooking into the refresh driver for
|
||||
* controlling animated images.
|
||||
*
|
||||
* @note The refresh driver owns a reference to these listeners.
|
||||
*
|
||||
* @note Technically, imgIRequest objects are not nsARefreshObservers, but
|
||||
* for controlling animated image repaint events, we subscribe the
|
||||
* imgIRequests to the nsRefreshDriver for notification of paint events.
|
||||
*
|
||||
* @returns whether the operation succeeded, or void in the case of removal.
|
||||
*/
|
||||
bool AddImageRequest(imgIRequest* aRequest);
|
||||
void RemoveImageRequest(imgIRequest* aRequest);
|
||||
void ClearAllImageRequests();
|
||||
|
||||
/**
|
||||
* Add / remove presshells that we should flush style and layout on
|
||||
*/
|
||||
|
@ -218,10 +239,15 @@ public:
|
|||
|
||||
private:
|
||||
typedef nsTObserverArray<nsARefreshObserver*> ObserverArray;
|
||||
typedef nsTHashtable<nsISupportsHashKey> RequestTable;
|
||||
|
||||
void EnsureTimerStarted(bool aAdjustingTimer);
|
||||
void StopTimer();
|
||||
|
||||
PRUint32 ObserverCount() const;
|
||||
PRUint32 ImageRequestCount() const;
|
||||
static PLDHashOperator ImageRequestEnumerator(nsISupportsHashKey* aEntry,
|
||||
void* aUserArg);
|
||||
void UpdateMostRecentRefresh();
|
||||
ObserverArray& ArrayFor(mozFlushType aFlushType);
|
||||
// Trigger a refresh immediately, if haven't been disconnected or frozen.
|
||||
|
@ -252,6 +278,8 @@ private:
|
|||
|
||||
// separate arrays for each flush type we support
|
||||
ObserverArray mObservers[3];
|
||||
RequestTable mRequests;
|
||||
|
||||
nsAutoTArray<nsIPresShell*, 16> mStyleFlushObservers;
|
||||
nsAutoTArray<nsIPresShell*, 16> mLayoutFlushObservers;
|
||||
// nsTArray on purpose, because we want to be able to swap.
|
||||
|
@ -262,6 +290,11 @@ private:
|
|||
// This is the last interval we used for our timer. May be 0 if we
|
||||
// haven't computed a timer interval yet.
|
||||
mutable PRInt32 mLastTimerInterval;
|
||||
|
||||
// Helper struct for processing image requests
|
||||
struct ImageRequestParameters {
|
||||
mozilla::TimeStamp ts;
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* !defined(nsRefreshDriver_h_) */
|
||||
|
|
Загрузка…
Ссылка в новой задаче