зеркало из https://github.com/mozilla/gecko-dev.git
Bug 795567 - Part 4: Rework apzc to wait for touch-action value from content as it waits for preventDefault value from listeners. r=kats
This commit is contained in:
Родитель
1651d2c5bb
Коммит
a9da19067c
|
@ -217,12 +217,12 @@ static const CSSToScreenScale MAX_ZOOM(8.0f);
|
|||
static const CSSToScreenScale MIN_ZOOM(0.125f);
|
||||
|
||||
/**
|
||||
* Amount of time before we timeout touch event listeners. For example, if
|
||||
* Amount of time before we timeout response from content. For example, if
|
||||
* content is being unruly/slow and we don't get a response back within this
|
||||
* time, we will just pretend that content did not preventDefault any touch
|
||||
* events we dispatched to it.
|
||||
*/
|
||||
static int gTouchListenerTimeout = 300;
|
||||
static int gContentResponseTimeout = 300;
|
||||
|
||||
/**
|
||||
* Number of samples to store of how long it took to paint after the previous
|
||||
|
@ -385,7 +385,7 @@ AsyncPanZoomController::InitializeGlobalState()
|
|||
Preferences::AddIntVarCache(&gPanRepaintInterval, "apz.pan_repaint_interval", gPanRepaintInterval);
|
||||
Preferences::AddIntVarCache(&gFlingRepaintInterval, "apz.fling_repaint_interval", gFlingRepaintInterval);
|
||||
Preferences::AddFloatVarCache(&gMinSkateSpeed, "apz.min_skate_speed", gMinSkateSpeed);
|
||||
Preferences::AddIntVarCache(&gTouchListenerTimeout, "apz.touch_listener_timeout", gTouchListenerTimeout);
|
||||
Preferences::AddIntVarCache(&gContentResponseTimeout, "apz.content_response_timeout", gContentResponseTimeout);
|
||||
Preferences::AddIntVarCache(&gNumPaintDurationSamples, "apz.num_paint_duration_samples", gNumPaintDurationSamples);
|
||||
Preferences::AddFloatVarCache(&gTouchStartTolerance, "apz.touch_start_tolerance", gTouchStartTolerance);
|
||||
Preferences::AddFloatVarCache(&gXSkateSizeMultiplier, "apz.x_skate_size_multiplier", gXSkateSizeMultiplier);
|
||||
|
@ -415,7 +415,7 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId,
|
|||
mRefPtrMonitor("RefPtrMonitor"),
|
||||
mMonitor("AsyncPanZoomController"),
|
||||
mTouchActionPropertyEnabled(gTouchActionPropertyEnabled),
|
||||
mTouchListenerTimeoutTask(nullptr),
|
||||
mContentResponseTimeoutTask(nullptr),
|
||||
mX(MOZ_THIS_IN_INITIALIZER_LIST()),
|
||||
mY(MOZ_THIS_IN_INITIALIZER_LIST()),
|
||||
mPanDirRestricted(false),
|
||||
|
@ -427,6 +427,9 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId,
|
|||
mCurrentAsyncScrollOffset(0, 0),
|
||||
mAsyncScrollTimeoutTask(nullptr),
|
||||
mHandlingTouchQueue(false),
|
||||
mAllowedTouchBehaviorSet(false),
|
||||
mPreventDefault(false),
|
||||
mPreventDefaultSet(false),
|
||||
mTreeManager(aTreeManager),
|
||||
mAPZCId(sAsyncPanZoomControllerCount++),
|
||||
mSharedFrameMetricsBuffer(nullptr),
|
||||
|
@ -501,30 +504,35 @@ AsyncPanZoomController::GetTouchStartTolerance()
|
|||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::ReceiveInputEvent(const InputData& aEvent) {
|
||||
// If we may have touch listeners, we enable the machinery that allows touch
|
||||
// listeners to preventDefault any touch inputs. This should not happen unless
|
||||
// there are actually touch listeners as it introduces potentially unbounded
|
||||
// lag because it causes a round-trip through content. Usually, if content is
|
||||
// responding in a timely fashion, this only introduces a nearly constant few
|
||||
// hundred ms of lag.
|
||||
// If we may have touch listeners and touch action property is enabled, we
|
||||
// enable the machinery that allows touch listeners to preventDefault any touch inputs
|
||||
// and also waits for the allowed touch behavior values to be received from the outside.
|
||||
// This should not happen unless there are actually touch listeners and touch-action property
|
||||
// enable as it introduces potentially unbounded lag because it causes a round-trip through
|
||||
// content. Usually, if content is responding in a timely fashion, this only introduces a
|
||||
// nearly constant few hundred ms of lag.
|
||||
if (mFrameMetrics.mMayHaveTouchListeners && aEvent.mInputType == MULTITOUCH_INPUT &&
|
||||
(mState == NOTHING || mState == TOUCHING || IsPanningState(mState))) {
|
||||
const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
|
||||
if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_START) {
|
||||
SetState(WAITING_LISTENERS);
|
||||
mAllowedTouchBehaviors.Clear();
|
||||
mAllowedTouchBehaviorSet = false;
|
||||
mPreventDefault = false;
|
||||
mPreventDefaultSet = false;
|
||||
SetState(WAITING_CONTENT_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (mState == WAITING_LISTENERS || mHandlingTouchQueue) {
|
||||
if (mState == WAITING_CONTENT_RESPONSE || mHandlingTouchQueue) {
|
||||
if (aEvent.mInputType == MULTITOUCH_INPUT) {
|
||||
const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
|
||||
mTouchQueue.AppendElement(multiTouchInput);
|
||||
|
||||
if (!mTouchListenerTimeoutTask) {
|
||||
mTouchListenerTimeoutTask =
|
||||
NewRunnableMethod(this, &AsyncPanZoomController::TimeoutTouchListeners);
|
||||
if (!mContentResponseTimeoutTask) {
|
||||
mContentResponseTimeoutTask =
|
||||
NewRunnableMethod(this, &AsyncPanZoomController::TimeoutContentResponse);
|
||||
|
||||
PostDelayedTask(mTouchListenerTimeoutTask, gTouchListenerTimeout);
|
||||
PostDelayedTask(mContentResponseTimeoutTask, gContentResponseTimeout);
|
||||
}
|
||||
}
|
||||
return nsEventStatus_eIgnore;
|
||||
|
@ -616,7 +624,7 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent
|
|||
case CROSS_SLIDING_X:
|
||||
case CROSS_SLIDING_Y:
|
||||
case PINCHING:
|
||||
case WAITING_LISTENERS:
|
||||
case WAITING_CONTENT_RESPONSE:
|
||||
NS_WARNING("Received impossible touch in OnTouchStart");
|
||||
break;
|
||||
default:
|
||||
|
@ -676,7 +684,7 @@ nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent)
|
|||
NS_WARNING("Gesture listener should have handled pinching in OnTouchMove.");
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
case WAITING_LISTENERS:
|
||||
case WAITING_CONTENT_RESPONSE:
|
||||
NS_WARNING("Received impossible touch in OnTouchMove");
|
||||
break;
|
||||
}
|
||||
|
@ -734,7 +742,7 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
|
|||
NS_WARNING("Gesture listener should have handled pinching in OnTouchEnd.");
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
case WAITING_LISTENERS:
|
||||
case WAITING_CONTENT_RESPONSE:
|
||||
NS_WARNING("Received impossible touch in OnTouchEnd");
|
||||
break;
|
||||
}
|
||||
|
@ -1668,25 +1676,40 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) {
|
|||
}
|
||||
|
||||
void AsyncPanZoomController::ContentReceivedTouch(bool aPreventDefault) {
|
||||
if (!mFrameMetrics.mMayHaveTouchListeners) {
|
||||
mTouchQueue.Clear();
|
||||
mPreventDefaultSet = true;
|
||||
mPreventDefault = aPreventDefault;
|
||||
CheckContentResponse();
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::CheckContentResponse() {
|
||||
bool canProceedToTouchState = true;
|
||||
|
||||
if (mFrameMetrics.mMayHaveTouchListeners) {
|
||||
canProceedToTouchState &= mPreventDefaultSet;
|
||||
}
|
||||
|
||||
if (mTouchActionPropertyEnabled) {
|
||||
canProceedToTouchState &= mAllowedTouchBehaviorSet;
|
||||
}
|
||||
|
||||
if (!canProceedToTouchState) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mTouchListenerTimeoutTask) {
|
||||
mTouchListenerTimeoutTask->Cancel();
|
||||
mTouchListenerTimeoutTask = nullptr;
|
||||
if (mContentResponseTimeoutTask) {
|
||||
mContentResponseTimeoutTask->Cancel();
|
||||
mContentResponseTimeoutTask = nullptr;
|
||||
}
|
||||
|
||||
if (mState == WAITING_LISTENERS) {
|
||||
if (!aPreventDefault) {
|
||||
if (mState == WAITING_CONTENT_RESPONSE) {
|
||||
if (!mPreventDefault) {
|
||||
SetState(NOTHING);
|
||||
}
|
||||
|
||||
mHandlingTouchQueue = true;
|
||||
|
||||
while (!mTouchQueue.IsEmpty()) {
|
||||
if (!aPreventDefault) {
|
||||
if (!mPreventDefault) {
|
||||
HandleInputEvent(mTouchQueue[0]);
|
||||
}
|
||||
|
||||
|
@ -1722,6 +1745,8 @@ AsyncPanZoomController::GetAllowedTouchBehavior(ScreenIntPoint& aPoint) {
|
|||
void AsyncPanZoomController::SetAllowedTouchBehavior(const nsTArray<TouchBehaviorFlags>& aBehaviors) {
|
||||
mAllowedTouchBehaviors.Clear();
|
||||
mAllowedTouchBehaviors.AppendElements(aBehaviors);
|
||||
mAllowedTouchBehaviorSet = true;
|
||||
CheckContentResponse();
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::SetState(PanZoomState aNewState) {
|
||||
|
@ -1747,15 +1772,15 @@ void AsyncPanZoomController::SetState(PanZoomState aNewState) {
|
|||
}
|
||||
|
||||
bool AsyncPanZoomController::IsTransformingState(PanZoomState aState) {
|
||||
return !(aState == NOTHING || aState == TOUCHING || aState == WAITING_LISTENERS);
|
||||
return !(aState == NOTHING || aState == TOUCHING || aState == WAITING_CONTENT_RESPONSE);
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::IsPanningState(PanZoomState aState) {
|
||||
return (aState == PANNING || aState == PANNING_LOCKED_X || aState == PANNING_LOCKED_Y);
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::TimeoutTouchListeners() {
|
||||
mTouchListenerTimeoutTask = nullptr;
|
||||
void AsyncPanZoomController::TimeoutContentResponse() {
|
||||
mContentResponseTimeoutTask = nullptr;
|
||||
ContentReceivedTouch(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -499,13 +499,13 @@ protected:
|
|||
const FrameMetrics& GetFrameMetrics();
|
||||
|
||||
/**
|
||||
* Timeout function for touch listeners. This should be called on a timer
|
||||
* Timeout function for content response. This should be called on a timer
|
||||
* after we get our first touch event in a batch, under the condition that we
|
||||
* have touch listeners. If a notification comes indicating whether or not
|
||||
* content preventDefaulted a series of touch events before the timeout, the
|
||||
* timeout should be cancelled.
|
||||
* waiting for response from content. If a notification comes indicating whether or not
|
||||
* content preventDefaulted a series of touch events and touch behavior values are
|
||||
* set before the timeout, the timeout should be cancelled.
|
||||
*/
|
||||
void TimeoutTouchListeners();
|
||||
void TimeoutContentResponse();
|
||||
|
||||
/**
|
||||
* Timeout function for mozbrowserasyncscroll event. Because we throttle
|
||||
|
@ -532,9 +532,10 @@ private:
|
|||
|
||||
PINCHING, /* nth touch-start, where n > 1. this mode allows pan and zoom */
|
||||
ANIMATING_ZOOM, /* animated zoom to a new rect */
|
||||
WAITING_LISTENERS, /* a state halfway between NOTHING and TOUCHING - the user has
|
||||
WAITING_CONTENT_RESPONSE, /* a state halfway between NOTHING and TOUCHING - the user has
|
||||
put a finger down, but we don't yet know if a touch listener has
|
||||
prevented the default actions yet. we still need to abort animations. */
|
||||
prevented the default actions yet and the allowed touch behavior
|
||||
was not set yet. we still need to abort animations. */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -544,6 +545,15 @@ private:
|
|||
*/
|
||||
TouchBehaviorFlags GetTouchBehavior(uint32_t touchIndex);
|
||||
|
||||
/**
|
||||
* To move from the WAITING_CONTENT_RESPONSE state to TOUCHING one we need two
|
||||
* conditions set: get content listeners response (whether they called preventDefault)
|
||||
* and get allowed touch behaviors.
|
||||
* This method checks both conditions and changes (or not changes) state
|
||||
* appropriately.
|
||||
*/
|
||||
void CheckContentResponse();
|
||||
|
||||
/**
|
||||
* Helper to set the current state. Holds the monitor before actually setting
|
||||
* it and fires content controller events based on state changes. Always set
|
||||
|
@ -621,7 +631,7 @@ private:
|
|||
|
||||
nsTArray<MultiTouchInput> mTouchQueue;
|
||||
|
||||
CancelableTask* mTouchListenerTimeoutTask;
|
||||
CancelableTask* mContentResponseTimeoutTask;
|
||||
|
||||
AxisX mX;
|
||||
AxisY mY;
|
||||
|
@ -674,6 +684,16 @@ private:
|
|||
// keeping an array of allowed touch behavior values, not the single value.
|
||||
nsTArray<TouchBehaviorFlags> mAllowedTouchBehaviors;
|
||||
|
||||
// Specifies whether mAllowedTouchBehaviors is set for current touch events block.
|
||||
bool mAllowedTouchBehaviorSet;
|
||||
|
||||
// Flag used to specify that content prevented the default behavior of the current
|
||||
// touch events block.
|
||||
bool mPreventDefault;
|
||||
|
||||
// Specifies whether mPreventDefault property is set for current touch events block.
|
||||
bool mPreventDefaultSet;
|
||||
|
||||
RefPtr<AsyncPanZoomAnimation> mAnimation;
|
||||
|
||||
friend class Axis;
|
||||
|
|
Загрузка…
Ссылка в новой задаче