mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1190469 - Refactor some code to have a general-purpose snap function available in APZC. r=botond (a4e8706df5) - Bug 1225761 - Clear axis lock in CancelAnimation and EndTouch. r=botond (1436279d0d) - Bug 1226316. Fixup to only expand displayport when skating with apz. r=kats (51c49a8fca) - Bug 1181703 - Allow re-entering the panning state if a second finger is tapped while panning with one finger. r=botond (e87cd85058) - Bug 1181703 - Add a gtest for making sure a pan can be continued after a second finger does a tap. r=botond (16354bec40) - Bug 1190469 - Request scroll snapping in a few places that animations are cancelled so that we don't leave things unsnapped. r=botond (4b0ba5e513) - Bug 960317 - Remove cross-slide code from APZC. r=botond (b2a045dbc9) - Bug 1231972 - Document how the apz.fling_friction pref is used. r=kats. DONTBUILD for comment change (c181588265) - Bug 1221593 - Don't reset other axis' scroll position during APZ drag. r=kats (9de4e134c6) - Bug 1219929 - Fix bad MouseInputData case. r=me (3630a3fcfa) - Bug 1211506 - Respect the APZ lock ordering in AsyncPanZoomController::OnScrollWheel(). r=mstange (3f152ffabf) - Bug 1229125 - Reset velocity in OnPanEnd if there's nowhere to scroll. r=botond (66ec61692a) - fix misspatch (f7aea52b9d) - Bug 1221186 - Don't clobber a fling-snap with a snap-to-where-we-are-now in the overscroll handoff chain. r=botond (7d4862bbe6) - Bug 1204932 - When C++APZ is enabled, elements that are zoomed with double tap should be centered. r=botond (b9e02a24b4) - Bug 1141884 - Rename ResetInputState and make it only apply to touch events. r=botond (aab239f51a) - Bug 1229125 - Correct velocity computation for pan gesture events. r=botond (b1f11b2e04) - Bug 1228559 - get MSG by audio channel type. r=roc (0e5e32f9bb) - Bug 1191207 - cancel chrome checking (74bde1263e) - Bug 1155469 - Mark nsTextEditorState::mTextCtrlElement as MOZ_NON_OWNING_REF; r=baku (7e6f4fa9d0) - Bug 1218072 - crash in nsTextEditorState::FinishedRestoringSelection, r=smaug (c7811e18ea) - bits of 1190258 (7f8fbbddfa) - Bug 1130237: [MSE] P1. Only ever return a frame if we have data. r=gerald (1ed595a5f8) - Bug 1130237: P2. Reset decoder state even if no decoder has been created yet. r=gerald (d352c0314b) - Bug 1130237: [MSE] P3. Add mochitest testing behavior. r=gerald (ce2b710a7e) - Bug 1229987: [MSE] P1. Ensure next random access point properly calculated after seek. r=gerald (d9a435f0b5)
This commit is contained in:
@@ -4824,7 +4824,7 @@ HTMLMediaElement::NotifyAudioChannelAgent(bool aPlaying)
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::WindowVolumeChanged(float aVolume, bool aMuted)
|
||||
{
|
||||
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
UpdateChannelMuteState(aVolume, aMuted);
|
||||
|
||||
@@ -4993,7 +4993,7 @@ NS_IMETHODIMP HTMLMediaElement::WindowAudioCaptureChanged()
|
||||
uint64_t id = window->WindowID();
|
||||
MediaStreamGraph* msg =
|
||||
MediaStreamGraph::GetInstance(MediaStreamGraph::AUDIO_THREAD_DRIVER,
|
||||
AudioChannel::Normal);
|
||||
mAudioChannel);
|
||||
|
||||
if (GetSrcMediaStream()) {
|
||||
mCaptureStreamPort = msg->ConnectToCaptureStream(id, GetSrcMediaStream());
|
||||
|
||||
@@ -110,7 +110,10 @@ public:
|
||||
}
|
||||
mTextEditorState->mSelectionRestoreEagerInit = false;
|
||||
}
|
||||
mTextEditorState->FinishedRestoringSelection();
|
||||
|
||||
if (mTextEditorState) {
|
||||
mTextEditorState->FinishedRestoringSelection();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "nsITextControlFrame.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
|
||||
class nsTextInputListener;
|
||||
@@ -282,7 +283,9 @@ private:
|
||||
friend class InitializationGuard;
|
||||
friend class PrepareEditorEvent;
|
||||
|
||||
nsITextControlElement* const mTextCtrlElement;
|
||||
// The text control element owns this object, and ensures that this object
|
||||
// has a smaller lifetime.
|
||||
nsITextControlElement* const MOZ_NON_OWNING_REF mTextCtrlElement;
|
||||
RefPtr<nsTextInputSelectionImpl> mSelCon;
|
||||
RefPtr<RestoreSelectionState> mRestoringSelection;
|
||||
nsCOMPtr<nsIEditor> mEditor;
|
||||
|
||||
@@ -476,9 +476,9 @@ VideoData::Create(const VideoInfo& aInfo,
|
||||
|
||||
MediaRawData::MediaRawData()
|
||||
: MediaData(RAW_DATA, 0)
|
||||
, mCrypto(mCryptoInternal)
|
||||
, mData(nullptr)
|
||||
, mSize(0)
|
||||
, mCrypto(mCryptoInternal)
|
||||
, mBuffer(nullptr)
|
||||
, mCapacity(0)
|
||||
{
|
||||
@@ -486,15 +486,17 @@ MediaRawData::MediaRawData()
|
||||
|
||||
MediaRawData::MediaRawData(const uint8_t* aData, size_t aSize)
|
||||
: MediaData(RAW_DATA, 0)
|
||||
, mCrypto(mCryptoInternal)
|
||||
, mData(nullptr)
|
||||
, mSize(0)
|
||||
, mCrypto(mCryptoInternal)
|
||||
, mBuffer(nullptr)
|
||||
, mCapacity(0)
|
||||
{
|
||||
if (!EnsureCapacity(aSize)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We ensure sufficient capacity above so this shouldn't fail.
|
||||
memcpy(mData, aData, aSize);
|
||||
mSize = aSize;
|
||||
}
|
||||
@@ -515,6 +517,7 @@ MediaRawData::Clone() const
|
||||
if (!s->EnsureCapacity(mSize)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
memcpy(s->mData, mData, mSize);
|
||||
s->mSize = mSize;
|
||||
}
|
||||
@@ -535,6 +538,7 @@ MediaRawData::EnsureCapacity(size_t aSize)
|
||||
if (!newBuffer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find alignment address.
|
||||
const uintptr_t alignmask = RAW_DATA_ALIGNMENT;
|
||||
uint8_t* newData = reinterpret_cast<uint8_t*>(
|
||||
@@ -557,7 +561,6 @@ size_t
|
||||
MediaRawData::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t size = aMallocSizeOf(this);
|
||||
|
||||
size += aMallocSizeOf(mBuffer.get());
|
||||
return size;
|
||||
}
|
||||
@@ -592,6 +595,7 @@ MediaRawDataWriter::SetSize(size_t aSize)
|
||||
if (aSize > mTarget->mSize && !EnsureSize(aSize)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mTarget->mSize = aSize;
|
||||
return true;
|
||||
}
|
||||
@@ -619,6 +623,7 @@ MediaRawDataWriter::Replace(const uint8_t* aData, size_t aSize)
|
||||
if (!EnsureSize(aSize)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(mTarget->mData, aData, aSize);
|
||||
mTarget->mSize = aSize;
|
||||
return true;
|
||||
|
||||
@@ -1244,6 +1244,7 @@ MediaFormatReader::Flush(TrackType aTrack)
|
||||
|
||||
auto& decoder = GetDecoderData(aTrack);
|
||||
if (!decoder.mDecoder) {
|
||||
decoder.ResetState();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -299,6 +299,7 @@ MediaSourceTrackDemuxer::MediaSourceTrackDemuxer(MediaSourceDemuxer* aParent,
|
||||
, mManager(aManager)
|
||||
, mType(aType)
|
||||
, mMonitor("MediaSourceTrackDemuxer")
|
||||
, mReset(true)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -331,6 +332,8 @@ MediaSourceTrackDemuxer::Reset()
|
||||
RefPtr<MediaSourceTrackDemuxer> self = this;
|
||||
nsCOMPtr<nsIRunnable> task =
|
||||
NS_NewRunnableFunction([self] () {
|
||||
self->mNextSample.reset();
|
||||
self->mReset = true;
|
||||
self->mManager->Seek(self->mType, TimeUnit(), TimeUnit());
|
||||
{
|
||||
MonitorAutoLock mon(self->mMonitor);
|
||||
@@ -388,6 +391,14 @@ MediaSourceTrackDemuxer::DoSeek(media::TimeUnit aTime)
|
||||
}
|
||||
TimeUnit seekTime =
|
||||
mManager->Seek(mType, aTime, MediaSourceDemuxer::EOS_FUZZ);
|
||||
bool error;
|
||||
RefPtr<MediaRawData> sample =
|
||||
mManager->GetSample(mType,
|
||||
media::TimeUnit(),
|
||||
error);
|
||||
MOZ_ASSERT(!error && sample);
|
||||
mNextSample = Some(sample);
|
||||
mReset = false;
|
||||
{
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
mNextRandomAccessPoint = mManager->GetNextRandomAccessPoint(mType);
|
||||
@@ -398,19 +409,34 @@ MediaSourceTrackDemuxer::DoSeek(media::TimeUnit aTime)
|
||||
RefPtr<MediaSourceTrackDemuxer::SamplesPromise>
|
||||
MediaSourceTrackDemuxer::DoGetSamples(int32_t aNumSamples)
|
||||
{
|
||||
bool error;
|
||||
RefPtr<MediaRawData> sample =
|
||||
mManager->GetSample(mType,
|
||||
MediaSourceDemuxer::EOS_FUZZ,
|
||||
error);
|
||||
if (mReset) {
|
||||
// If a seek (or reset) was recently performed, we ensure that the data
|
||||
// we are about to retrieve is still available.
|
||||
TimeIntervals buffered = mManager->Buffered(mType);
|
||||
buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ);
|
||||
|
||||
if (!sample) {
|
||||
if (error) {
|
||||
return SamplesPromise::CreateAndReject(DemuxerFailureReason::DEMUXER_ERROR, __func__);
|
||||
if (!buffered.Contains(TimeUnit::FromMicroseconds(0))) {
|
||||
return SamplesPromise::CreateAndReject(
|
||||
mManager->IsEnded() ? DemuxerFailureReason::END_OF_STREAM :
|
||||
DemuxerFailureReason::WAITING_FOR_DATA, __func__);
|
||||
}
|
||||
mReset = false;
|
||||
}
|
||||
bool error = false;
|
||||
RefPtr<MediaRawData> sample;
|
||||
if (mNextSample) {
|
||||
sample = mNextSample.ref();
|
||||
mNextSample.reset();
|
||||
} else {
|
||||
sample = mManager->GetSample(mType, MediaSourceDemuxer::EOS_FUZZ, error);
|
||||
if (!sample) {
|
||||
if (error) {
|
||||
return SamplesPromise::CreateAndReject(DemuxerFailureReason::DEMUXER_ERROR, __func__);
|
||||
}
|
||||
return SamplesPromise::CreateAndReject(
|
||||
mManager->IsEnded() ? DemuxerFailureReason::END_OF_STREAM :
|
||||
DemuxerFailureReason::WAITING_FOR_DATA, __func__);
|
||||
}
|
||||
return SamplesPromise::CreateAndReject(
|
||||
mManager->IsEnded() ? DemuxerFailureReason::END_OF_STREAM :
|
||||
DemuxerFailureReason::WAITING_FOR_DATA, __func__);
|
||||
}
|
||||
RefPtr<SamplesHolder> samples = new SamplesHolder;
|
||||
samples->mSamples.AppendElement(sample);
|
||||
|
||||
@@ -130,6 +130,10 @@ private:
|
||||
// Monitor protecting members below accessed from multiple threads.
|
||||
Monitor mMonitor;
|
||||
media::TimeUnit mNextRandomAccessPoint;
|
||||
Maybe<RefPtr<MediaRawData>> mNextSample;
|
||||
// Set to true following a reset. Ensure that the next sample demuxed
|
||||
// is available at position 0.
|
||||
bool mReset;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -42,6 +42,8 @@ skip-if = true # bug 1182946
|
||||
skip-if = true # bug 1182946
|
||||
[test_HaveMetadataUnbufferedSeek_mp4.html]
|
||||
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
|
||||
[test_LoadedDataFired_mp4.html]
|
||||
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
|
||||
[test_LiveSeekable.html]
|
||||
[test_LoadedMetadataFired.html]
|
||||
skip-if = true # bug 1182946
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>MSE: Check that playback only starts once we have data at time = 0</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="mediasource.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
runWithMSE(function(ms, el) {
|
||||
el.controls = true;
|
||||
el.addEventListener("loadeddata", function() {
|
||||
ok(el.buffered.length > 0, "data is buffered");
|
||||
is(el.buffered.start(0), 0, "must fire loadeddata when data has been loaded");
|
||||
is(el.currentTime, 0, "must fire loadeddata at start");
|
||||
});
|
||||
el.addEventListener("playing", function() {
|
||||
ok(el.buffered.length > 0, "data is buffered");
|
||||
is(el.buffered.start(0), 0, "must fire playing when data has been loaded");
|
||||
is(el.currentTime, 0, "must fire playing at start");
|
||||
});
|
||||
once(ms, 'sourceopen').then(function() {
|
||||
ok(true, "Receive a sourceopen event");
|
||||
var videosb = ms.addSourceBuffer("video/mp4");
|
||||
is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING");
|
||||
fetchAndLoad(videosb, 'bipbop/bipbop_video', ['init'], '.mp4')
|
||||
.then(once.bind(null, el, "loadedmetadata"))
|
||||
.then(function() {
|
||||
videosb.appendWindowStart = 2;
|
||||
videosb.appendWindowEnd = 4;
|
||||
is(el.readyState, el.HAVE_METADATA, "readyState is HAVE_METADATA");
|
||||
// Load [2.4, 3.968344). 2.4 as it's the first keyframe after 2s and
|
||||
// 3.968344 as the last frame ends after 4s.
|
||||
return fetchAndLoad(videosb, 'bipbop/bipbop_video', range(1, 8), '.m4s');
|
||||
})
|
||||
.then(function() {
|
||||
is(el.readyState, el.HAVE_METADATA, "readyState is HAVE_METADATA");
|
||||
// test that appendWindowEnd did its job.
|
||||
ok(el.buffered.start(0) >= 2, "no data can be found prior appendWindowStart");
|
||||
ok(el.buffered.end(el.buffered.length-1) <= 4, "no data can be found beyond appendWindowEnd");
|
||||
el.play();
|
||||
return once(el, "play");
|
||||
})
|
||||
.then(function() {
|
||||
videosb.appendWindowStart = 0;
|
||||
var promises = [];
|
||||
// Load [0, 3.971666).
|
||||
promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', range(1, 8), '.m4s'));
|
||||
// playback can only start now.
|
||||
promises.push(once(el, "playing"));
|
||||
return Promise.all(promises);
|
||||
})
|
||||
.then(function() {
|
||||
ok(true, "playing");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -21,10 +21,18 @@ enum HitTestResult {
|
||||
};
|
||||
|
||||
enum CancelAnimationFlags : uint32_t {
|
||||
Default = 0, /* Cancel all animations */
|
||||
ExcludeOverscroll = 1 /* Don't clear overscroll */
|
||||
Default = 0x0, /* Cancel all animations */
|
||||
ExcludeOverscroll = 0x1, /* Don't clear overscroll */
|
||||
RequestSnap = 0x2 /* Request snapping to snap points */
|
||||
};
|
||||
|
||||
inline CancelAnimationFlags
|
||||
operator|(CancelAnimationFlags a, CancelAnimationFlags b)
|
||||
{
|
||||
return static_cast<CancelAnimationFlags>(static_cast<int>(a)
|
||||
| static_cast<int>(b));
|
||||
}
|
||||
|
||||
enum class ScrollSource {
|
||||
// scrollTo() or something similar.
|
||||
DOM,
|
||||
|
||||
@@ -139,9 +139,6 @@ using mozilla::gfx::PointTyped;
|
||||
* events we dispatched to it.\n
|
||||
* Units: milliseconds
|
||||
*
|
||||
* \li\b apz.cross_slide_enabled
|
||||
* Pref that enables integration with the Metro "cross-slide" gesture.
|
||||
*
|
||||
* \li\b apz.danger_zone_x
|
||||
* \li\b apz.danger_zone_y
|
||||
* When drawing high-res tiles, we drop down to drawing low-res tiles
|
||||
@@ -201,8 +198,11 @@ using mozilla::gfx::PointTyped;
|
||||
* http://mxr.mozilla.org/mozilla-central/source/layout/style/nsStyleStruct.cpp?rev=21282be9ad95#2462
|
||||
*
|
||||
* \li\b apz.fling_friction
|
||||
* Amount of friction applied during flings.
|
||||
*
|
||||
* Amount of friction applied during flings. This is used in the following
|
||||
* formula: v(t1) = v(t0) * (1 - f)^(t1 - t0), where v(t1) is the velocity
|
||||
* for a new sample, v(t0) is the velocity at the previous sample, f is the
|
||||
* value of this pref, and (t1 - t0) is the amount of time, in milliseconds,
|
||||
* that has elapsed between the two samples.
|
||||
*
|
||||
* \li\b apz.fling_repaint_interval
|
||||
* Maximum amount of time flinging before sending a viewport change. This will
|
||||
@@ -684,7 +684,14 @@ public:
|
||||
bool continueX = mApzc.mX.SampleOverscrollAnimation(aDelta);
|
||||
bool continueY = mApzc.mY.SampleOverscrollAnimation(aDelta);
|
||||
if (!continueX && !continueY) {
|
||||
mApzc.OverscrollAnimationEnding();
|
||||
// If we got into overscroll from a fling, that fling did not request a
|
||||
// fling snap to avoid a resulting scrollTo from cancelling the overscroll
|
||||
// animation too early. We do still want to request a fling snap, though,
|
||||
// in case the end of the axis at which we're overscrolled is not a valid
|
||||
// snap point, so we request one now. If there are no snap points, this will
|
||||
// do nothing. If there are snap points, we'll get a scrollTo that snaps us
|
||||
// back to the nearest valid snap point.
|
||||
mApzc.RequestSnap();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -908,7 +915,7 @@ AsyncPanZoomController::Destroy()
|
||||
{
|
||||
APZThreadUtils::AssertOnCompositorThread();
|
||||
|
||||
CancelAnimation();
|
||||
CancelAnimation(CancelAnimationFlags::RequestSnap);
|
||||
|
||||
{ // scope the lock
|
||||
MonitorAutoLock lock(mRefPtrMonitor);
|
||||
@@ -1032,8 +1039,8 @@ nsEventStatus AsyncPanZoomController::HandleDragEvent(const MouseInput& aEvent,
|
||||
CSSPoint scrollFramePoint = aEvent.mLocalOrigin / GetFrameMetrics().GetZoom();
|
||||
// The scrollbar can be transformed with the frame but the pres shell
|
||||
// resolution is only applied to the scroll frame.
|
||||
CSSPoint scrollbarPoint = scrollFramePoint * GetFrameMetrics().GetPresShellResolution();
|
||||
CSSRect cssCompositionBound = GetFrameMetrics().GetCompositionBounds() / GetFrameMetrics().GetZoom();
|
||||
CSSPoint scrollbarPoint = scrollFramePoint * mFrameMetrics.GetPresShellResolution();
|
||||
CSSRect cssCompositionBound = mFrameMetrics.CalculateCompositedRectInCssPixels();
|
||||
|
||||
float mousePosition = GetAxisStart(aDragMetrics.mDirection, scrollbarPoint) -
|
||||
aDragMetrics.mScrollbarDragOffset -
|
||||
@@ -1042,34 +1049,31 @@ nsEventStatus AsyncPanZoomController::HandleDragEvent(const MouseInput& aEvent,
|
||||
|
||||
float scrollMax = GetAxisEnd(aDragMetrics.mDirection, aDragMetrics.mScrollTrack);
|
||||
scrollMax -= node->GetScrollSize() /
|
||||
GetAxisScale(aDragMetrics.mDirection, GetFrameMetrics().GetZoom()) *
|
||||
GetFrameMetrics().GetPresShellResolution();
|
||||
GetAxisScale(aDragMetrics.mDirection, mFrameMetrics.GetZoom()) *
|
||||
mFrameMetrics.GetPresShellResolution();
|
||||
|
||||
float scrollPercent = mousePosition / scrollMax;
|
||||
|
||||
float minScrollPosition =
|
||||
GetAxisStart(aDragMetrics.mDirection, GetFrameMetrics().GetScrollableRect().TopLeft());
|
||||
GetAxisStart(aDragMetrics.mDirection, mFrameMetrics.GetScrollableRect().TopLeft());
|
||||
float maxScrollPosition =
|
||||
GetAxisSize(aDragMetrics.mDirection, GetFrameMetrics().GetScrollableRect()) -
|
||||
GetAxisSize(aDragMetrics.mDirection, GetFrameMetrics().GetCompositionBounds());
|
||||
GetAxisSize(aDragMetrics.mDirection, mFrameMetrics.GetScrollableRect()) -
|
||||
GetAxisSize(aDragMetrics.mDirection, mFrameMetrics.GetCompositionBounds());
|
||||
float scrollPosition = scrollPercent * maxScrollPosition;
|
||||
|
||||
scrollPosition = std::max(scrollPosition, minScrollPosition);
|
||||
scrollPosition = std::min(scrollPosition, maxScrollPosition);
|
||||
|
||||
CSSPoint scrollOffset;
|
||||
CSSPoint scrollOffset = mFrameMetrics.GetScrollOffset();
|
||||
if (aDragMetrics.mDirection == AsyncDragMetrics::HORIZONTAL) {
|
||||
scrollOffset = CSSPoint(scrollPosition, 0);
|
||||
scrollOffset.x = scrollPosition;
|
||||
} else {
|
||||
scrollOffset = CSSPoint(0, scrollPosition);
|
||||
scrollOffset.y = scrollPosition;
|
||||
}
|
||||
mFrameMetrics.SetScrollOffset(scrollOffset);
|
||||
ScheduleCompositeAndMaybeRepaint();
|
||||
UpdateSharedCompositorFrameMetrics();
|
||||
|
||||
// Here we consume the events. This means that the content scrollbars
|
||||
// will only see the initial mouse down and the final mouse up.
|
||||
// APZ will still update the scroll position.
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
@@ -1123,13 +1127,13 @@ nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent,
|
||||
break;
|
||||
}
|
||||
case MOUSE_INPUT: {
|
||||
ScrollWheelInput scrollInput = aEvent.AsScrollWheelInput();
|
||||
if (!scrollInput.TransformToLocal(aTransformToApzc)) {
|
||||
MouseInput mouseInput = aEvent.AsMouseInput();
|
||||
if (!mouseInput.TransformToLocal(aTransformToApzc)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// TODO Need to implement blocks to properly handle this.
|
||||
//rv = HandleDragEvent(scrollInput, dragMetrics);
|
||||
//rv = HandleDragEvent(mouseInput, dragMetrics);
|
||||
break;
|
||||
}
|
||||
case SCROLLWHEEL_INPUT: {
|
||||
@@ -1230,8 +1234,6 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent
|
||||
case PANNING:
|
||||
case PANNING_LOCKED_X:
|
||||
case PANNING_LOCKED_Y:
|
||||
case CROSS_SLIDING_X:
|
||||
case CROSS_SLIDING_Y:
|
||||
case PINCHING:
|
||||
NS_WARNING("Received impossible touch in OnTouchStart");
|
||||
break;
|
||||
@@ -1254,12 +1256,6 @@ nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent)
|
||||
// second tap. Ignore the move if this happens.
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
case CROSS_SLIDING_X:
|
||||
case CROSS_SLIDING_Y:
|
||||
// While cross-sliding, we don't want to consume any touchmove events for
|
||||
// panning or zooming, and let the caller handle them instead.
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
case TOUCHING: {
|
||||
ScreenCoord panThreshold = GetTouchStartTolerance();
|
||||
UpdateWithTouchAtDevicePoint(aEvent);
|
||||
@@ -1331,16 +1327,22 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
case TOUCHING:
|
||||
case CROSS_SLIDING_X:
|
||||
case CROSS_SLIDING_Y:
|
||||
// We may have some velocity stored on the axis from move events
|
||||
// that were not big enough to trigger scrolling. Clear that out.
|
||||
mX.SetVelocity(0);
|
||||
mY.SetVelocity(0);
|
||||
// It's possible we may be overscrolled if the user tapped during a
|
||||
// previous overscroll pan. Make sure to snap back in this situation.
|
||||
if (!SnapBackIfOverscrolled()) {
|
||||
SetState(NOTHING);
|
||||
APZC_LOG("%p still has %u touch points active\n", this,
|
||||
CurrentTouchBlock()->GetActiveTouchCount());
|
||||
// In cases where the user is panning, then taps the second finger without
|
||||
// entering a pinch, we will arrive here when the second finger is lifted.
|
||||
// However the first finger is still down so we want to remain in state
|
||||
// TOUCHING.
|
||||
if (CurrentTouchBlock()->GetActiveTouchCount() == 0) {
|
||||
// It's possible we may be overscrolled if the user tapped during a
|
||||
// previous overscroll pan. Make sure to snap back in this situation.
|
||||
if (!SnapBackIfOverscrolled()) {
|
||||
SetState(NOTHING);
|
||||
}
|
||||
}
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
@@ -1535,6 +1537,10 @@ nsEventStatus AsyncPanZoomController::OnScaleEnd(const PinchGestureInput& aEvent
|
||||
} else {
|
||||
ClearOverscroll();
|
||||
}
|
||||
// Along with clearing the overscroll, we also want to snap to the nearest
|
||||
// snap point as appropriate, so ask the main thread (which knows about such
|
||||
// things) to handle it.
|
||||
RequestSnap();
|
||||
|
||||
ScheduleComposite();
|
||||
RequestContentRepaint();
|
||||
@@ -1749,12 +1755,9 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
|
||||
|
||||
switch (aEvent.mScrollMode) {
|
||||
case ScrollWheelInput::SCROLLMODE_INSTANT: {
|
||||
// Call ToScreenCoordinates outside the lock because it grabs the tree lock.
|
||||
ScreenPoint distance = ToScreenCoordinates(
|
||||
ParentLayerPoint(fabs(delta.x), fabs(delta.y)), aEvent.mLocalOrigin);
|
||||
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
|
||||
CancelAnimation();
|
||||
SetState(WHEEL_SCROLL);
|
||||
|
||||
@@ -1767,6 +1770,10 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
|
||||
CallDispatchScroll(startPoint, endPoint, handoffState);
|
||||
|
||||
SetState(NOTHING);
|
||||
|
||||
// The calls above handle their own locking; moreover,
|
||||
// ToScreenCoordinates() and CallDispatchScroll() can grab the tree lock.
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
RequestContentRepaint();
|
||||
|
||||
break;
|
||||
@@ -1933,6 +1940,19 @@ nsEventStatus AsyncPanZoomController::OnPanEnd(const PanGestureInput& aEvent) {
|
||||
|
||||
mX.EndTouch(aEvent.mTime);
|
||||
mY.EndTouch(aEvent.mTime);
|
||||
|
||||
// Drop any velocity on axes where we don't have room to scroll anyways
|
||||
// (in this APZC, or an APZC further in the handoff chain).
|
||||
// This ensures that we don't enlarge the display port unnecessarily.
|
||||
RefPtr<const OverscrollHandoffChain> overscrollHandoffChain =
|
||||
CurrentPanGestureBlock()->GetOverscrollHandoffChain();
|
||||
if (!overscrollHandoffChain->CanScrollInDirection(this, Layer::HORIZONTAL)) {
|
||||
mX.SetVelocity(0);
|
||||
}
|
||||
if (!overscrollHandoffChain->CanScrollInDirection(this, Layer::VERTICAL)) {
|
||||
mY.SetVelocity(0);
|
||||
}
|
||||
|
||||
SetState(NOTHING);
|
||||
RequestContentRepaint();
|
||||
|
||||
@@ -2182,24 +2202,17 @@ void AsyncPanZoomController::HandlePanning(double aAngle) {
|
||||
bool canScrollVertical = !mY.IsAxisLocked() &&
|
||||
overscrollHandoffChain->CanScrollInDirection(this, Layer::VERTICAL);
|
||||
|
||||
if (!gfxPrefs::APZCrossSlideEnabled() &&
|
||||
(!canScrollHorizontal || !canScrollVertical)) {
|
||||
if (!canScrollHorizontal || !canScrollVertical) {
|
||||
SetState(PANNING);
|
||||
} else if (IsCloseToHorizontal(aAngle, gfxPrefs::APZAxisLockAngle())) {
|
||||
mY.SetAxisLocked(true);
|
||||
if (canScrollHorizontal) {
|
||||
SetState(PANNING_LOCKED_X);
|
||||
} else {
|
||||
SetState(CROSS_SLIDING_X);
|
||||
mX.SetAxisLocked(true);
|
||||
}
|
||||
} else if (IsCloseToVertical(aAngle, gfxPrefs::APZAxisLockAngle())) {
|
||||
mX.SetAxisLocked(true);
|
||||
if (canScrollVertical) {
|
||||
SetState(PANNING_LOCKED_Y);
|
||||
} else {
|
||||
SetState(CROSS_SLIDING_Y);
|
||||
mY.SetAxisLocked(true);
|
||||
}
|
||||
} else {
|
||||
SetState(PANNING);
|
||||
@@ -2216,13 +2229,13 @@ void AsyncPanZoomController::HandlePanningUpdate(const ScreenPoint& aPanDistance
|
||||
float breakThreshold = gfxPrefs::APZAxisBreakoutThreshold() * APZCTreeManager::GetDPI();
|
||||
|
||||
if (fabs(aPanDistance.x) > breakThreshold || fabs(aPanDistance.y) > breakThreshold) {
|
||||
if (mState == PANNING_LOCKED_X || mState == CROSS_SLIDING_X) {
|
||||
if (mState == PANNING_LOCKED_X) {
|
||||
if (!IsCloseToHorizontal(angle, gfxPrefs::APZAxisBreakoutAngle())) {
|
||||
mY.SetAxisLocked(false);
|
||||
SetState(PANNING);
|
||||
}
|
||||
} else if (mState == PANNING_LOCKED_Y || mState == CROSS_SLIDING_Y) {
|
||||
if (!IsCloseToVertical(angle, gfxPrefs::APZAxisLockAngle())) {
|
||||
} else if (mState == PANNING_LOCKED_Y) {
|
||||
if (!IsCloseToVertical(angle, gfxPrefs::APZAxisBreakoutAngle())) {
|
||||
mX.SetAxisLocked(false);
|
||||
SetState(PANNING);
|
||||
}
|
||||
@@ -2568,6 +2581,8 @@ void AsyncPanZoomController::CancelAnimation(CancelAnimationFlags aFlags) {
|
||||
bool repaint = !IsZero(GetVelocityVector());
|
||||
mX.SetVelocity(0);
|
||||
mY.SetVelocity(0);
|
||||
mX.SetAxisLocked(false);
|
||||
mY.SetAxisLocked(false);
|
||||
// Setting the state to nothing and cancelling the animation can
|
||||
// preempt normal mechanisms for relieving overscroll, so we need to clear
|
||||
// overscroll here.
|
||||
@@ -2575,6 +2590,11 @@ void AsyncPanZoomController::CancelAnimation(CancelAnimationFlags aFlags) {
|
||||
ClearOverscroll();
|
||||
repaint = true;
|
||||
}
|
||||
// Similar to relieving overscroll, we also need to snap to any snap points
|
||||
// if appropriate, so ask the main thread to do that.
|
||||
if (aFlags & CancelAnimationFlags::RequestSnap) {
|
||||
RequestSnap();
|
||||
}
|
||||
if (repaint) {
|
||||
RequestContentRepaint();
|
||||
ScheduleComposite();
|
||||
@@ -2617,15 +2637,20 @@ static CSSSize
|
||||
CalculateDisplayPortSize(const CSSSize& aCompositionSize,
|
||||
const CSSPoint& aVelocity)
|
||||
{
|
||||
float xMultiplier = fabsf(aVelocity.x) < gfxPrefs::APZMinSkateSpeed()
|
||||
bool xIsStationarySpeed = fabsf(aVelocity.x) < gfxPrefs::APZMinSkateSpeed();
|
||||
bool yIsStationarySpeed = fabsf(aVelocity.y) < gfxPrefs::APZMinSkateSpeed();
|
||||
float xMultiplier = xIsStationarySpeed
|
||||
? gfxPrefs::APZXStationarySizeMultiplier()
|
||||
: gfxPrefs::APZXSkateSizeMultiplier();
|
||||
float yMultiplier = fabsf(aVelocity.y) < gfxPrefs::APZMinSkateSpeed()
|
||||
float yMultiplier = yIsStationarySpeed
|
||||
? gfxPrefs::APZYStationarySizeMultiplier()
|
||||
: gfxPrefs::APZYSkateSizeMultiplier();
|
||||
|
||||
if (IsHighMemSystem()) {
|
||||
if (IsHighMemSystem() && !xIsStationarySpeed) {
|
||||
xMultiplier += gfxPrefs::APZXSkateHighMemAdjust();
|
||||
}
|
||||
|
||||
if (IsHighMemSystem() && !yIsStationarySpeed) {
|
||||
yMultiplier += gfxPrefs::APZYSkateHighMemAdjust();
|
||||
}
|
||||
|
||||
@@ -2745,6 +2770,12 @@ bool AsyncPanZoomController::SnapBackIfOverscrolled() {
|
||||
StartOverscrollAnimation(ParentLayerPoint(0, 0));
|
||||
return true;
|
||||
}
|
||||
// If we don't kick off an overscroll animation, we still need to ask the
|
||||
// main thread to snap to any nearby snap points, assuming we haven't already
|
||||
// done so when we started this fling
|
||||
if (mState != FLING) {
|
||||
RequestSnap();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3314,13 +3345,16 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) {
|
||||
targetZoom = CSSToParentLayerScale(std::min(compositionBounds.width / aRect.width,
|
||||
compositionBounds.height / aRect.height));
|
||||
}
|
||||
// 1. If the rect is empty, request received from browserElementScrolling.js
|
||||
// 1. If the rect is empty, the content-side logic for handling a double-tap
|
||||
// requested that we zoom out.
|
||||
// 2. currentZoom is equal to mZoomConstraints.mMaxZoom and user still double-tapping it
|
||||
// 3. currentZoom is equal to localMinZoom and user still double-tapping it
|
||||
// Treat these three cases as a request to zoom out as much as possible.
|
||||
bool zoomOut = false;
|
||||
if (aRect.IsEmpty() ||
|
||||
(currentZoom == localMaxZoom && targetZoom >= localMaxZoom) ||
|
||||
(currentZoom == localMinZoom && targetZoom <= localMinZoom)) {
|
||||
zoomOut = true;
|
||||
CSSSize compositedSize = mFrameMetrics.CalculateCompositedSizeInCssPixels();
|
||||
float y = scrollOffset.y;
|
||||
float newHeight =
|
||||
@@ -3354,6 +3388,14 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) {
|
||||
aRect.x = aRect.x > 0 ? aRect.x : 0;
|
||||
}
|
||||
|
||||
// Vertically center the zoomed element in the screen.
|
||||
if (!zoomOut && (sizeAfterZoom.height > aRect.height)) {
|
||||
aRect.y -= (sizeAfterZoom.height - aRect.height) * 0.5f;
|
||||
if (aRect.y < 0.0f) {
|
||||
aRect.y = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
endZoomToMetrics.SetScrollOffset(aRect.TopLeft());
|
||||
endZoomToMetrics.SetDisplayPortMargins(
|
||||
CalculatePendingDisplayPort(endZoomToMetrics, ParentLayerPoint(0,0)));
|
||||
@@ -3390,11 +3432,8 @@ AsyncPanZoomController::CurrentPanGestureBlock() const
|
||||
}
|
||||
|
||||
void
|
||||
AsyncPanZoomController::ResetInputState()
|
||||
AsyncPanZoomController::ResetTouchInputState()
|
||||
{
|
||||
// This may be called during non-touch input blocks as well. We send
|
||||
// a fake cancel touch event here but on the assumption that none of the
|
||||
// code in GEL assumes a CurrentTouchBlock()
|
||||
MultiTouchInput cancel(MultiTouchInput::MULTITOUCH_CANCEL, 0, TimeStamp::Now(), 0);
|
||||
RefPtr<GestureEventListener> listener = GetGestureEventListener();
|
||||
if (listener) {
|
||||
@@ -3408,7 +3447,7 @@ AsyncPanZoomController::CancelAnimationAndGestureState()
|
||||
{
|
||||
mX.CancelGesture();
|
||||
mY.CancelGesture();
|
||||
CancelAnimation();
|
||||
CancelAnimation(CancelAnimationFlags::RequestSnap);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -3573,15 +3612,10 @@ void AsyncPanZoomController::ShareCompositorFrameMetrics() {
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::OverscrollAnimationEnding() {
|
||||
// If we got into overscroll from a fling, that fling did not request a
|
||||
// fling snap to avoid a resulting scrollTo from cancelling the overscroll
|
||||
// animation too early. We do still want to request a fling snap, though,
|
||||
// in case the end of the axis at which we're overscrolled is not a valid
|
||||
// snap point, so we request one now. If there are no snap points, this will
|
||||
// do nothing. If there are snap points, we'll get a scrollTo that snaps us
|
||||
// back to the nearest valid snap point.
|
||||
void AsyncPanZoomController::RequestSnap() {
|
||||
if (RefPtr<GeckoContentController> controller = GetGeckoContentController()) {
|
||||
APZC_LOG("%p requesting snap near %s\n", this,
|
||||
Stringify(mFrameMetrics.GetScrollOffset()).c_str());
|
||||
controller->RequestFlingSnap(mFrameMetrics.GetScrollId(),
|
||||
mFrameMetrics.GetScrollOffset());
|
||||
}
|
||||
|
||||
@@ -636,9 +636,10 @@ protected:
|
||||
// Common processing at the end of a touch block.
|
||||
void OnTouchEndOrCancel();
|
||||
|
||||
// This is called by OverscrollAnimation to notify us when the overscroll
|
||||
// animation is ending.
|
||||
void OverscrollAnimationEnding();
|
||||
// This is called to request that the main thread snap the scroll position
|
||||
// to a nearby snap position if appropriate. The current scroll position is
|
||||
// used as the final destination.
|
||||
void RequestSnap();
|
||||
|
||||
uint64_t mLayersId;
|
||||
RefPtr<CompositorParent> mCompositorParent;
|
||||
@@ -741,11 +742,6 @@ protected:
|
||||
|
||||
PAN_MOMENTUM, /* like PANNING, but controlled by momentum PanGestureInput events */
|
||||
|
||||
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 */
|
||||
OVERSCROLL_ANIMATION, /* Spring-based animation used to relieve overscroll once
|
||||
@@ -805,9 +801,9 @@ public:
|
||||
bool ArePointerEventsConsumable(TouchBlockState* aBlock, uint32_t aTouchPoints);
|
||||
|
||||
/**
|
||||
* Clear internal state relating to input handling.
|
||||
* Clear internal state relating to touch input handling.
|
||||
*/
|
||||
void ResetInputState();
|
||||
void ResetTouchInputState();
|
||||
|
||||
private:
|
||||
void CancelAnimationAndGestureState();
|
||||
|
||||
@@ -76,7 +76,7 @@ void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, ParentLayerCoord
|
||||
return;
|
||||
}
|
||||
|
||||
float newVelocity = mAxisLocked ? 0.0f : (float)(mPos - aPos - aAdditionalDelta) / (float)(aTimestampMs - mPosTimeMs);
|
||||
float newVelocity = mAxisLocked ? 0.0f : (float)(mPos - aPos + aAdditionalDelta) / (float)(aTimestampMs - mPosTimeMs);
|
||||
if (gfxPrefs::APZMaxVelocity() > 0.0f) {
|
||||
bool velocityIsNegative = (newVelocity < 0);
|
||||
newVelocity = fabs(newVelocity);
|
||||
@@ -382,6 +382,7 @@ void Axis::EndTouch(uint32_t aTimestampMs) {
|
||||
// mVelocityQueue is controller-thread only
|
||||
APZThreadUtils::AssertOnControllerThread();
|
||||
|
||||
mAxisLocked = false;
|
||||
mVelocity = 0;
|
||||
int count = 0;
|
||||
while (!mVelocityQueue.IsEmpty()) {
|
||||
|
||||
@@ -887,5 +887,11 @@ TouchBlockState::UpdateSlopState(const MultiTouchInput& aInput,
|
||||
return mInSlop;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TouchBlockState::GetActiveTouchCount() const
|
||||
{
|
||||
return mTouchCounter.GetActiveTouchCount();
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -453,6 +453,11 @@ public:
|
||||
bool UpdateSlopState(const MultiTouchInput& aInput,
|
||||
bool aApzcCanConsumeEvents);
|
||||
|
||||
/**
|
||||
* Returns the number of touch points currently active.
|
||||
*/
|
||||
uint32_t GetActiveTouchCount() const;
|
||||
|
||||
bool HasEvents() const override;
|
||||
void DropEvents() override;
|
||||
void HandleEvents() override;
|
||||
|
||||
@@ -661,7 +661,9 @@ InputQueue::ProcessInputBlocks() {
|
||||
curBlock->DropEvents();
|
||||
} else if (curBlock->IsDefaultPrevented()) {
|
||||
curBlock->DropEvents();
|
||||
target->ResetInputState();
|
||||
if (curBlock->AsTouchBlock()) {
|
||||
target->ResetTouchInputState();
|
||||
}
|
||||
} else {
|
||||
UpdateActiveApzc(curBlock->GetTargetApzc());
|
||||
curBlock->HandleEvents();
|
||||
@@ -687,7 +689,7 @@ void
|
||||
InputQueue::UpdateActiveApzc(const RefPtr<AsyncPanZoomController>& aNewActive) {
|
||||
if (mLastActiveApzc && mLastActiveApzc != aNewActive
|
||||
&& mTouchCounter.GetActiveTouchCount() > 0) {
|
||||
mLastActiveApzc->ResetInputState();
|
||||
mLastActiveApzc->ResetTouchInputState();
|
||||
}
|
||||
mLastActiveApzc = aNewActive;
|
||||
}
|
||||
|
||||
@@ -917,6 +917,81 @@ TEST_F(APZCPinchGestureDetectorTester, Pinch_PreventDefault) {
|
||||
apzc->AssertStateIsReset();
|
||||
}
|
||||
|
||||
TEST_F(APZCGestureDetectorTester, Pan_With_Tap) {
|
||||
SCOPED_GFX_PREF(TouchActionEnabled, bool, false);
|
||||
|
||||
FrameMetrics originalMetrics = GetPinchableFrameMetrics();
|
||||
apzc->SetFrameMetrics(originalMetrics);
|
||||
|
||||
// Making the APZC zoomable isn't really needed for the correct operation of
|
||||
// this test, but it could help catch regressions where we accidentally enter
|
||||
// a pinch state.
|
||||
MakeApzcZoomable();
|
||||
|
||||
// Test parameters
|
||||
int touchX = 250;
|
||||
int touchY = 300;
|
||||
int panDistance = 20;
|
||||
|
||||
int firstFingerId = 0;
|
||||
int secondFingerId = firstFingerId + 1;
|
||||
|
||||
// Put finger down
|
||||
MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, 0, TimeStamp(), 0);
|
||||
mti.mTouches.AppendElement(CreateSingleTouchData(firstFingerId, touchX, touchY));
|
||||
apzc->ReceiveInputEvent(mti, nullptr);
|
||||
|
||||
// Start a pan, break through the threshold
|
||||
touchY += 40;
|
||||
mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, TimeStamp(), 0);
|
||||
mti.mTouches.AppendElement(CreateSingleTouchData(firstFingerId, touchX, touchY));
|
||||
apzc->ReceiveInputEvent(mti, nullptr);
|
||||
|
||||
// Do an actual pan for a bit
|
||||
touchY += panDistance;
|
||||
mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, TimeStamp(), 0);
|
||||
mti.mTouches.AppendElement(CreateSingleTouchData(firstFingerId, touchX, touchY));
|
||||
apzc->ReceiveInputEvent(mti, nullptr);
|
||||
|
||||
// Put a second finger down
|
||||
mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, 0, TimeStamp(), 0);
|
||||
mti.mTouches.AppendElement(CreateSingleTouchData(firstFingerId, touchX, touchY));
|
||||
mti.mTouches.AppendElement(CreateSingleTouchData(secondFingerId, touchX + 10, touchY));
|
||||
apzc->ReceiveInputEvent(mti, nullptr);
|
||||
|
||||
// Lift the second finger
|
||||
mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, 0, TimeStamp(), 0);
|
||||
mti.mTouches.AppendElement(CreateSingleTouchData(secondFingerId, touchX + 10, touchY));
|
||||
apzc->ReceiveInputEvent(mti, nullptr);
|
||||
|
||||
// Bust through the threshold again
|
||||
touchY += 40;
|
||||
mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, TimeStamp(), 0);
|
||||
mti.mTouches.AppendElement(CreateSingleTouchData(firstFingerId, touchX, touchY));
|
||||
apzc->ReceiveInputEvent(mti, nullptr);
|
||||
|
||||
// Do some more actual panning
|
||||
touchY += panDistance;
|
||||
mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, TimeStamp(), 0);
|
||||
mti.mTouches.AppendElement(CreateSingleTouchData(firstFingerId, touchX, touchY));
|
||||
apzc->ReceiveInputEvent(mti, nullptr);
|
||||
|
||||
// Lift the first finger
|
||||
mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, 0, TimeStamp(), 0);
|
||||
mti.mTouches.AppendElement(CreateSingleTouchData(firstFingerId, touchX, touchY));
|
||||
apzc->ReceiveInputEvent(mti, nullptr);
|
||||
|
||||
// Verify that we scrolled
|
||||
FrameMetrics finalMetrics = apzc->GetFrameMetrics();
|
||||
float zoom = finalMetrics.GetZoom().ToScaleFactor().scale;
|
||||
EXPECT_EQ(originalMetrics.GetScrollOffset().y - (panDistance * 2 / zoom), finalMetrics.GetScrollOffset().y);
|
||||
|
||||
// Clear out any remaining fling animation and pending tasks
|
||||
apzc->AdvanceAnimationsUntilEnd();
|
||||
while (mcc->RunThroughDelayedTasks());
|
||||
apzc->AssertStateIsReset();
|
||||
}
|
||||
|
||||
TEST_F(APZCBasicTester, Overzoom) {
|
||||
// the visible area of the document in CSS pixels is x=10 y=0 w=100 h=100
|
||||
FrameMetrics fm;
|
||||
|
||||
@@ -146,7 +146,6 @@ private:
|
||||
DECL_GFX_PREF(Live, "apz.axis_lock.lock_angle", APZAxisLockAngle, float, float(M_PI / 6.0) /* 30 degrees */);
|
||||
DECL_GFX_PREF(Live, "apz.axis_lock.mode", APZAxisLockMode, int32_t, 0);
|
||||
DECL_GFX_PREF(Live, "apz.content_response_timeout", APZContentResponseTimeout, int32_t, 300);
|
||||
DECL_GFX_PREF(Live, "apz.cross_slide.enabled", APZCrossSlideEnabled, bool, false);
|
||||
DECL_GFX_PREF(Live, "apz.danger_zone_x", APZDangerZoneX, int32_t, 50);
|
||||
DECL_GFX_PREF(Live, "apz.danger_zone_y", APZDangerZoneY, int32_t, 100);
|
||||
DECL_GFX_PREF(Live, "apz.drag.enabled", APZDragEnabled, bool, false);
|
||||
|
||||
@@ -595,7 +595,6 @@ pref("apz.axis_lock.breakout_threshold", "0.03125"); // 1/32 inches
|
||||
pref("apz.axis_lock.breakout_angle", "0.3926991"); // PI / 8 (22.5 degrees)
|
||||
pref("apz.axis_lock.direct_pan_angle", "1.047197"); // PI / 3 (60 degrees)
|
||||
pref("apz.content_response_timeout", 300);
|
||||
pref("apz.cross_slide.enabled", false);
|
||||
pref("apz.drag.enabled", false);
|
||||
pref("apz.danger_zone_x", 50);
|
||||
pref("apz.danger_zone_y", 100);
|
||||
|
||||
Reference in New Issue
Block a user