Bug 1053766 - Add a StateChange notification blocker to APZC. r=botond

This commit is contained in:
Kartikaya Gupta 2014-09-12 11:39:56 -04:00
parent a39f9fd831
commit 1a41b340db
2 changed files with 106 additions and 43 deletions

View File

@ -408,6 +408,32 @@ GetFrameTime() {
return sFrameTime;
}
class MOZ_STACK_CLASS StateChangeNotificationBlocker {
public:
StateChangeNotificationBlocker(AsyncPanZoomController* aApzc)
: mApzc(aApzc)
{
ReentrantMonitorAutoEnter lock(mApzc->mMonitor);
mInitialState = mApzc->mState;
mApzc->mNotificationBlockers++;
}
~StateChangeNotificationBlocker()
{
AsyncPanZoomController::PanZoomState newState;
{
ReentrantMonitorAutoEnter lock(mApzc->mMonitor);
mApzc->mNotificationBlockers--;
newState = mApzc->mState;
}
mApzc->DispatchStateChangeNotification(mInitialState, newState);
}
private:
AsyncPanZoomController* mApzc;
AsyncPanZoomController::PanZoomState mInitialState;
};
class FlingAnimation: public AsyncPanZoomAnimation {
public:
FlingAnimation(AsyncPanZoomController& aApzc,
@ -848,7 +874,6 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId,
mRefPtrMonitor("RefPtrMonitor"),
mSharingFrameMetricsAcrossProcesses(false),
mMonitor("AsyncPanZoomController"),
mState(NOTHING),
mX(MOZ_THIS_IN_INITIALIZER_LIST()),
mY(MOZ_THIS_IN_INITIALIZER_LIST()),
mPanDirRestricted(false),
@ -858,6 +883,8 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId,
mLastAsyncScrollOffset(0, 0),
mCurrentAsyncScrollOffset(0, 0),
mAsyncScrollTimeoutTask(nullptr),
mState(NOTHING),
mNotificationBlockers(0),
mTouchBlockBalance(0),
mTreeManager(aTreeManager),
mAPZCId(sAsyncPanZoomControllerCount++),
@ -2999,8 +3026,8 @@ AsyncPanZoomController::GetAllowedTouchBehavior(ScreenIntPoint& aPoint) {
return AllowedTouchBehavior::UNKNOWN;
}
void AsyncPanZoomController::SetState(PanZoomState aNewState) {
void AsyncPanZoomController::SetState(PanZoomState aNewState)
{
PanZoomState oldState;
// Intentional scoping for mutex
@ -3010,11 +3037,24 @@ void AsyncPanZoomController::SetState(PanZoomState aNewState) {
mState = aNewState;
}
DispatchStateChangeNotification(oldState, aNewState);
}
void AsyncPanZoomController::DispatchStateChangeNotification(PanZoomState aOldState,
PanZoomState aNewState)
{
{ // scope the lock
ReentrantMonitorAutoEnter lock(mMonitor);
if (mNotificationBlockers > 0) {
return;
}
}
if (nsRefPtr<GeckoContentController> controller = GetGeckoContentController()) {
if (!IsTransformingState(oldState) && IsTransformingState(aNewState)) {
if (!IsTransformingState(aOldState) && IsTransformingState(aNewState)) {
controller->NotifyAPZStateChange(
GetGuid(), APZStateChange::TransformBegin);
} else if (IsTransformingState(oldState) && !IsTransformingState(aNewState)) {
} else if (IsTransformingState(aOldState) && !IsTransformingState(aNewState)) {
controller->NotifyAPZStateChange(
GetGuid(), APZStateChange::TransformEnd);
}

View File

@ -45,6 +45,7 @@ class FlingAnimation;
class InputBlockState;
class TouchBlockState;
class OverscrollHandoffChain;
class StateChangeNotificationBlocker;
/**
* Controller for all panning and zooming logic. Any time a user input is
@ -350,27 +351,6 @@ public:
const ScreenPoint& aAnchor) const;
protected:
enum PanZoomState {
NOTHING, /* no touch-start events received */
FLING, /* all touches removed, but we're still scrolling page */
TOUCHING, /* one touch-start event received */
PANNING, /* panning the frame */
PANNING_LOCKED_X, /* touch-start followed by move (i.e. panning with axis lock) X axis */
PANNING_LOCKED_Y, /* as above for Y axis */
CROSS_SLIDING_X, /* Panning disabled while user does a horizontal gesture
on a vertically-scrollable view. This used for the
Windows Metro "cross-slide" gesture. */
CROSS_SLIDING_Y, /* as above for Y axis */
PINCHING, /* nth touch-start, where n > 1. this mode allows pan and zoom */
ANIMATING_ZOOM, /* animated zoom to a new rect */
SNAP_BACK, /* snap-back animation to relieve overscroll */
SMOOTH_SCROLL, /* Smooth scrolling to destination. Used by
CSSOM-View smooth scroll-behavior */
};
// Protected destructor, to discourage deletion outside of Release():
~AsyncPanZoomController();
@ -596,13 +576,6 @@ private:
*/
bool ArePointerEventsConsumable(TouchBlockState* aBlock, uint32_t aTouchPoints);
/**
* Helper to set the current state. Holds the monitor before actually setting
* it and fires content controller events based on state changes. Always set
* the state using this call, do not set it directly.
*/
void SetState(PanZoomState aState);
/**
* Convert ScreenPoint relative to this APZC to CSSPoint relative
* to the parent document. This excludes the transient compositor transform.
@ -611,12 +584,6 @@ private:
*/
bool ConvertToGecko(const ScreenPoint& aPoint, CSSPoint* aOut);
/**
* Internal helpers for checking general state of this apzc.
*/
static bool IsTransformingState(PanZoomState aState);
bool IsInPanningState() const;
/**
* Return in |aTransform| a visual effect that reflects this apzc's
* overscrolled state, if any.
@ -682,10 +649,6 @@ protected:
// would significantly limit what methods could be 'const'.
mutable ReentrantMonitor mMonitor;
// Stores the state of panning and zooming this frame. This is protected by
// |mMonitor|; that is, it should be held whenever this is updated.
PanZoomState mState;
private:
// Metrics of the container layer corresponding to this APZC. This is
// stored here so that it is accessible from the UI/controller thread.
@ -741,6 +704,66 @@ private:
friend class Axis;
/* ===================================================================
* The functions and members in this section are used to manage
* the state that tracks what this APZC is doing with the input events.
*/
protected:
enum PanZoomState {
NOTHING, /* no touch-start events received */
FLING, /* all touches removed, but we're still scrolling page */
TOUCHING, /* one touch-start event received */
PANNING, /* panning the frame */
PANNING_LOCKED_X, /* touch-start followed by move (i.e. panning with axis lock) X axis */
PANNING_LOCKED_Y, /* as above for Y axis */
CROSS_SLIDING_X, /* Panning disabled while user does a horizontal gesture
on a vertically-scrollable view. This used for the
Windows Metro "cross-slide" gesture. */
CROSS_SLIDING_Y, /* as above for Y axis */
PINCHING, /* nth touch-start, where n > 1. this mode allows pan and zoom */
ANIMATING_ZOOM, /* animated zoom to a new rect */
SNAP_BACK, /* snap-back animation to relieve overscroll */
SMOOTH_SCROLL, /* Smooth scrolling to destination. Used by
CSSOM-View smooth scroll-behavior */
};
// This is in theory protected by |mMonitor|; that is, it should be held whenever
// this is updated. In practice though... see bug 897017.
PanZoomState mState;
private:
friend class StateChangeNotificationBlocker;
/**
* A counter of how many StateChangeNotificationBlockers are active.
* A non-zero count will prevent state change notifications from
* being dispatched. Only code that holds mMonitor should touch this.
*/
int mNotificationBlockers;
/**
* Helper to set the current state. Holds the monitor before actually setting
* it and fires content controller events based on state changes. Always set
* the state using this call, do not set it directly.
*/
void SetState(PanZoomState aState);
/**
* Fire content controller notifications about state changes, assuming no
* StateChangeNotificationBlocker has been activated.
*/
void DispatchStateChangeNotification(PanZoomState aOldState, PanZoomState aNewState);
/**
* Internal helpers for checking general state of this apzc.
*/
static bool IsTransformingState(PanZoomState aState);
bool IsInPanningState() const;
/* ===================================================================
* The functions and members in this section are used to manage
* blocks of touch events and the state needed to deal with content