mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out 3 changesets (bug 1022818
) for B2G test failures on a CLOSED TREE.
Backed out changeset 9b37b8ae8302 (bug1022818
) Backed out changeset bfe7d53e220a (bug1022818
) Backed out changeset 6c5208ca3274 (bug1022818
)
This commit is contained in:
parent
c5e7dd1786
commit
d62988fcbb
@ -35,7 +35,6 @@
|
||||
#include "nsAttrValue.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/WindowBinding.h"
|
||||
#include "Units.h"
|
||||
|
||||
class nsIDOMEventListener;
|
||||
@ -716,8 +715,11 @@ public:
|
||||
already_AddRefed<ShadowRoot> CreateShadowRoot(ErrorResult& aError);
|
||||
already_AddRefed<DestinationInsertionPointList> GetDestinationInsertionPoints();
|
||||
|
||||
void ScrollIntoView();
|
||||
void ScrollIntoView(bool aTop, const ScrollOptions &aOptions);
|
||||
void ScrollIntoView()
|
||||
{
|
||||
ScrollIntoView(true);
|
||||
}
|
||||
void ScrollIntoView(bool aTop);
|
||||
int32_t ScrollTop()
|
||||
{
|
||||
nsIScrollableFrame* sf = GetScrollFrame();
|
||||
|
@ -585,13 +585,7 @@ Element::GetScrollFrame(nsIFrame **aStyledFrame, bool aFlushLayout)
|
||||
}
|
||||
|
||||
void
|
||||
Element::ScrollIntoView()
|
||||
{
|
||||
ScrollIntoView(true, ScrollOptions());
|
||||
}
|
||||
|
||||
void
|
||||
Element::ScrollIntoView(bool aTop, const ScrollOptions &aOptions)
|
||||
Element::ScrollIntoView(bool aTop)
|
||||
{
|
||||
nsIDocument *document = GetCurrentDoc();
|
||||
if (!document) {
|
||||
@ -607,17 +601,12 @@ Element::ScrollIntoView(bool aTop, const ScrollOptions &aOptions)
|
||||
int16_t vpercent = aTop ? nsIPresShell::SCROLL_TOP :
|
||||
nsIPresShell::SCROLL_BOTTOM;
|
||||
|
||||
uint32_t flags = nsIPresShell::SCROLL_OVERFLOW_HIDDEN;
|
||||
if (aOptions.mBehavior == ScrollBehavior::Smooth) {
|
||||
flags |= nsIPresShell::SCROLL_SMOOTH;
|
||||
}
|
||||
|
||||
presShell->ScrollContentIntoView(this,
|
||||
nsIPresShell::ScrollAxis(
|
||||
vpercent,
|
||||
nsIPresShell::SCROLL_ALWAYS),
|
||||
nsIPresShell::ScrollAxis(),
|
||||
flags);
|
||||
nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -469,7 +469,7 @@ public:
|
||||
if (!_argc) {
|
||||
top = true;
|
||||
}
|
||||
mozilla::dom::Element::ScrollIntoView(top, mozilla::dom::ScrollOptions());
|
||||
mozilla::dom::Element::ScrollIntoView(top);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHOD GetOffsetParent(nsIDOMElement** aOffsetParent) MOZ_FINAL {
|
||||
|
@ -7200,37 +7200,22 @@ nsGlobalWindow::GetTopWindowRoot()
|
||||
return window.forget();
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::Scroll(int32_t aXScroll, int32_t aYScroll,
|
||||
const ScrollOptions& aOptions)
|
||||
{
|
||||
ScrollTo(CSSIntPoint(aXScroll, aYScroll), aOptions);
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::ScrollTo(int32_t aXScroll, int32_t aYScroll,
|
||||
const ScrollOptions& aOptions)
|
||||
{
|
||||
ScrollTo(CSSIntPoint(aXScroll, aYScroll), aOptions);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::Scroll(int32_t aXScroll, int32_t aYScroll)
|
||||
{
|
||||
ScrollTo(CSSIntPoint(aXScroll, aYScroll), ScrollOptions());
|
||||
ScrollTo(CSSIntPoint(aXScroll, aYScroll));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::ScrollTo(int32_t aXScroll, int32_t aYScroll)
|
||||
{
|
||||
ScrollTo(CSSIntPoint(aXScroll, aYScroll), ScrollOptions());
|
||||
ScrollTo(CSSIntPoint(aXScroll, aYScroll));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::ScrollTo(const CSSIntPoint& aScroll,
|
||||
const ScrollOptions& aOptions)
|
||||
nsGlobalWindow::ScrollTo(const CSSIntPoint& aScroll)
|
||||
{
|
||||
FlushPendingNotifications(Flush_Layout);
|
||||
nsIScrollableFrame *sf = GetScrollFrame();
|
||||
@ -7251,86 +7236,7 @@ nsGlobalWindow::ScrollTo(const CSSIntPoint& aScroll,
|
||||
if (scroll.y > maxpx) {
|
||||
scroll.y = maxpx;
|
||||
}
|
||||
|
||||
sf->ScrollToCSSPixels(scroll,
|
||||
aOptions.mBehavior == ScrollBehavior::Smooth
|
||||
? nsIScrollableFrame::SMOOTH_MSD
|
||||
: nsIScrollableFrame::INSTANT);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::ScrollBy(int32_t aXScrollDif, int32_t aYScrollDif)
|
||||
{
|
||||
ScrollBy(aXScrollDif, aYScrollDif, ScrollOptions());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::ScrollBy(int32_t aXScrollDif, int32_t aYScrollDif,
|
||||
const ScrollOptions& aOptions)
|
||||
{
|
||||
FlushPendingNotifications(Flush_Layout);
|
||||
nsIScrollableFrame *sf = GetScrollFrame();
|
||||
|
||||
if (sf) {
|
||||
CSSIntPoint scrollPos =
|
||||
sf->GetScrollPositionCSSPixels() + CSSIntPoint(aXScrollDif, aYScrollDif);
|
||||
// It seems like it would make more sense for ScrollBy to use
|
||||
// SMOOTH mode, but tests seem to depend on the synchronous behaviour.
|
||||
// Perhaps Web content does too.
|
||||
ScrollTo(scrollPos, aOptions);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::ScrollByLines(int32_t numLines)
|
||||
{
|
||||
ScrollByLines(numLines, ScrollOptions());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::ScrollByLines(int32_t numLines,
|
||||
const ScrollOptions& aOptions)
|
||||
{
|
||||
FlushPendingNotifications(Flush_Layout);
|
||||
nsIScrollableFrame *sf = GetScrollFrame();
|
||||
if (sf) {
|
||||
// It seems like it would make more sense for ScrollByLines to use
|
||||
// SMOOTH mode, but tests seem to depend on the synchronous behaviour.
|
||||
// Perhaps Web content does too.
|
||||
sf->ScrollBy(nsIntPoint(0, numLines), nsIScrollableFrame::LINES,
|
||||
aOptions.mBehavior == ScrollBehavior::Smooth
|
||||
? nsIScrollableFrame::SMOOTH_MSD
|
||||
: nsIScrollableFrame::INSTANT);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::ScrollByPages(int32_t numPages)
|
||||
{
|
||||
ScrollByPages(numPages, ScrollOptions());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::ScrollByPages(int32_t numPages,
|
||||
const ScrollOptions& aOptions)
|
||||
{
|
||||
FlushPendingNotifications(Flush_Layout);
|
||||
nsIScrollableFrame *sf = GetScrollFrame();
|
||||
if (sf) {
|
||||
// It seems like it would make more sense for ScrollByPages to use
|
||||
// SMOOTH mode, but tests seem to depend on the synchronous behaviour.
|
||||
// Perhaps Web content does too.
|
||||
sf->ScrollBy(nsIntPoint(0, numPages), nsIScrollableFrame::PAGES,
|
||||
aOptions.mBehavior == ScrollBehavior::Smooth
|
||||
? nsIScrollableFrame::SMOOTH_MSD
|
||||
: nsIScrollableFrame::INSTANT);
|
||||
sf->ScrollToCSSPixels(scroll);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7350,6 +7256,56 @@ nsGlobalWindow::MozRequestOverfill(OverfillCallback& aCallback,
|
||||
aError.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::ScrollBy(int32_t aXScrollDif, int32_t aYScrollDif)
|
||||
{
|
||||
FlushPendingNotifications(Flush_Layout);
|
||||
nsIScrollableFrame *sf = GetScrollFrame();
|
||||
|
||||
if (sf) {
|
||||
CSSIntPoint scrollPos =
|
||||
sf->GetScrollPositionCSSPixels() + CSSIntPoint(aXScrollDif, aYScrollDif);
|
||||
// It seems like it would make more sense for ScrollBy to use
|
||||
// SMOOTH mode, but tests seem to depend on the synchronous behaviour.
|
||||
// Perhaps Web content does too.
|
||||
ScrollTo(scrollPos);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::ScrollByLines(int32_t numLines)
|
||||
{
|
||||
FlushPendingNotifications(Flush_Layout);
|
||||
nsIScrollableFrame *sf = GetScrollFrame();
|
||||
if (sf) {
|
||||
// It seems like it would make more sense for ScrollByLines to use
|
||||
// SMOOTH mode, but tests seem to depend on the synchronous behaviour.
|
||||
// Perhaps Web content does too.
|
||||
sf->ScrollBy(nsIntPoint(0, numLines), nsIScrollableFrame::LINES,
|
||||
nsIScrollableFrame::INSTANT);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::ScrollByPages(int32_t numPages)
|
||||
{
|
||||
FlushPendingNotifications(Flush_Layout);
|
||||
nsIScrollableFrame *sf = GetScrollFrame();
|
||||
if (sf) {
|
||||
// It seems like it would make more sense for ScrollByPages to use
|
||||
// SMOOTH mode, but tests seem to depend on the synchronous behaviour.
|
||||
// Perhaps Web content does too.
|
||||
sf->ScrollBy(nsIntPoint(0, numPages), nsIScrollableFrame::PAGES,
|
||||
nsIScrollableFrame::INSTANT);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::ClearTimeout(int32_t aHandle, ErrorResult& aError)
|
||||
{
|
||||
|
@ -49,7 +49,6 @@
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMTouchEvent.h"
|
||||
#include "mozilla/dom/EventTarget.h"
|
||||
#include "mozilla/dom/WindowBinding.h"
|
||||
#include "Units.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
|
||||
@ -935,16 +934,6 @@ public:
|
||||
mozilla::ErrorResult& aError);
|
||||
void ResizeBy(int32_t aWidthDif, int32_t aHeightDif,
|
||||
mozilla::ErrorResult& aError);
|
||||
void Scroll(int32_t aXScroll, int32_t aYScroll,
|
||||
const mozilla::dom::ScrollOptions& aOptions);
|
||||
void ScrollTo(int32_t aXScroll, int32_t aYScroll,
|
||||
const mozilla::dom::ScrollOptions& aOptions);
|
||||
void ScrollBy(int32_t aXScrollDif, int32_t aYScrollDif,
|
||||
const mozilla::dom::ScrollOptions& aOptions);
|
||||
void ScrollByLines(int32_t numLines,
|
||||
const mozilla::dom::ScrollOptions& aOptions);
|
||||
void ScrollByPages(int32_t numPages,
|
||||
const mozilla::dom::ScrollOptions& aOptions);
|
||||
int32_t GetInnerWidth(mozilla::ErrorResult& aError);
|
||||
void SetInnerWidth(int32_t aInnerWidth, mozilla::ErrorResult& aError);
|
||||
int32_t GetInnerHeight(mozilla::ErrorResult& aError);
|
||||
@ -1322,8 +1311,7 @@ public:
|
||||
mozilla::ErrorResult& aError);
|
||||
nsRect GetInnerScreenRect();
|
||||
|
||||
void ScrollTo(const mozilla::CSSIntPoint& aScroll,
|
||||
const mozilla::dom::ScrollOptions& aOptions);
|
||||
void ScrollTo(const mozilla::CSSIntPoint& aScroll);
|
||||
|
||||
bool IsFrame()
|
||||
{
|
||||
|
@ -153,7 +153,7 @@ partial interface Element {
|
||||
|
||||
// scrolling
|
||||
void scrollIntoView();
|
||||
void scrollIntoView(boolean top, optional ScrollOptions options);
|
||||
void scrollIntoView(boolean top);
|
||||
// None of the CSSOM attributes are [Pure], because they flush
|
||||
attribute long scrollTop; // scroll on setting
|
||||
attribute long scrollLeft; // scroll on setting
|
||||
|
@ -179,13 +179,16 @@ partial interface Window {
|
||||
//[Throws] readonly attribute double pageXOffset;
|
||||
//[Throws] readonly attribute double scrollY;
|
||||
//[Throws] readonly attribute double pageYOffset;
|
||||
void scroll(double x, double y, optional ScrollOptions options);
|
||||
void scrollTo(double x, double y, optional ScrollOptions options);
|
||||
void scrollBy(double x, double y, optional ScrollOptions options);
|
||||
//void scroll(double x, double y, optional ScrollOptions options);
|
||||
//void scrollTo(double x, double y, optional ScrollOptions options);
|
||||
//void scrollBy(double x, double y, optional ScrollOptions options);
|
||||
[Replaceable, Throws] readonly attribute long scrollX;
|
||||
[Throws] readonly attribute long pageXOffset;
|
||||
[Replaceable, Throws] readonly attribute long scrollY;
|
||||
[Throws] readonly attribute long pageYOffset;
|
||||
void scroll(long x, long y);
|
||||
void scrollTo(long x, long y);
|
||||
void scrollBy(long x, long y);
|
||||
|
||||
// client
|
||||
//[Throws] readonly attribute double screenX;
|
||||
@ -268,12 +271,12 @@ partial interface Window {
|
||||
/**
|
||||
* Method for scrolling this window by a number of lines.
|
||||
*/
|
||||
void scrollByLines(long numLines, optional ScrollOptions options);
|
||||
void scrollByLines(long numLines);
|
||||
|
||||
/**
|
||||
* Method for scrolling this window by a number of pages.
|
||||
*/
|
||||
void scrollByPages(long numPages, optional ScrollOptions options);
|
||||
void scrollByPages(long numPages);
|
||||
|
||||
/**
|
||||
* Method for sizing this window to the content in the window.
|
||||
|
@ -681,10 +681,6 @@ public:
|
||||
* If SCROLL_NO_PARENT_FRAMES is set then we only scroll
|
||||
* nodes in this document, not in any parent documents which
|
||||
* contain this document in a iframe or the like.
|
||||
* If SCROLL_SMOOTH is set and CSSOM-VIEW scroll-behavior
|
||||
* is enabled, we will scroll smoothly using
|
||||
* nsIScrollableFrame::ScrollMode::SMOOTH_MSD; otherwise,
|
||||
* nsIScrollableFrame::ScrollMode::INSTANT will be used.
|
||||
*/
|
||||
virtual nsresult ScrollContentIntoView(nsIContent* aContent,
|
||||
ScrollAxis aVertical,
|
||||
@ -694,8 +690,7 @@ public:
|
||||
enum {
|
||||
SCROLL_FIRST_ANCESTOR_ONLY = 0x01,
|
||||
SCROLL_OVERFLOW_HIDDEN = 0x02,
|
||||
SCROLL_NO_PARENT_FRAMES = 0x04,
|
||||
SCROLL_SMOOTH = 0x08
|
||||
SCROLL_NO_PARENT_FRAMES = 0x04
|
||||
};
|
||||
/**
|
||||
* Scrolls the view of the document so that the given area of a frame
|
||||
|
@ -3519,11 +3519,7 @@ static void ScrollToShowRect(nsIFrame* aFrame,
|
||||
// If we don't need to scroll, then don't try since it might cancel
|
||||
// a current smooth scroll operation.
|
||||
if (needToScroll) {
|
||||
nsIScrollableFrame::ScrollMode scrollMode = nsIScrollableFrame::INSTANT;
|
||||
if (gfxPrefs::ScrollBehaviorEnabled() && aFlags & nsIPresShell::SCROLL_SMOOTH) {
|
||||
scrollMode = nsIScrollableFrame::SMOOTH_MSD;
|
||||
}
|
||||
aFrameAsScrollable->ScrollTo(scrollPt, scrollMode, &allowedRange);
|
||||
aFrameAsScrollable->ScrollTo(scrollPt, nsIScrollableFrame::INSTANT, &allowedRange);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,6 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || e10s # b2g(plugins not sup
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
|
||||
[test_plugin_position.xhtml]
|
||||
skip-if = e10s
|
||||
[test_scroll_behavior.html]
|
||||
[test_selection_expanding.html]
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' # b2g(mouse selection not working) b2g-debug(mouse selection not working) b2g-desktop(mouse selection not working)
|
||||
support-files = selection_expanding_xbl.xml
|
||||
|
@ -1,252 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tests for CSSOM-View Smooth-Scroll DOM API Methods and MSD Animation</title>
|
||||
<style>
|
||||
#scroll_behavior_test_body {
|
||||
width: 100000px;
|
||||
height: 100000px;
|
||||
}
|
||||
.scroll_to_target {
|
||||
position: absolute;
|
||||
left: 20000px;
|
||||
top: 10000px;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background-color: rgb(0, 0, 255);
|
||||
}
|
||||
</style>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function clamp(val, min_val, max_val) {
|
||||
return Math.max(min_val, Math.min(max_val, val));
|
||||
}
|
||||
|
||||
window.addEventListener("load", function(event) {
|
||||
if (event.target == document) {
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{ 'set': [['layout.css.scroll-behavior.enabled', true]] },
|
||||
function () {
|
||||
test_scroll_behavior_interruption();
|
||||
test_scroll_behavior_framerate();
|
||||
|
||||
window.scrollTo(0, 0);
|
||||
SimpleTest.finish();
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
}, false);
|
||||
|
||||
|
||||
function test_scroll_behavior_interruption() {
|
||||
// Take control of refresh driver
|
||||
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(0);
|
||||
|
||||
window.scrollTo(10, 9);
|
||||
ok(window.scrollX == 10 && window.scrollY == 9,
|
||||
"instant scroll-behavior must be synchronous when setting initial position");
|
||||
|
||||
window.scrollTo(15, 16);
|
||||
ok(window.scrollX == 15 && window.scrollY == 16,
|
||||
"instant scroll-behavior must be synchronous when setting new position");
|
||||
|
||||
window.scrollTo(100, 200, {behavior: 'smooth'});
|
||||
ok(window.scrollX == 15 && window.scrollY == 16,
|
||||
"smooth scroll-behavior must be asynchronous");
|
||||
|
||||
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(100);
|
||||
ok(window.scrollX != 15 && window.scrollY != 16
|
||||
&& window.scrollX != 100 && window.scrollY != 200,
|
||||
"smooth scroll-behavior must be triggered by window.scrollTo");
|
||||
|
||||
window.scrollTo(50, 52);
|
||||
ok(window.scrollX == 50 && window.scrollY == 52,
|
||||
"instant scroll-behavior must interrupt smooth scroll-behavior animation");
|
||||
|
||||
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(100);
|
||||
ok(window.scrollX == 50 && window.scrollY == 52,
|
||||
"smooth scroll-behavior animation must stop after being interrupted");
|
||||
|
||||
// Release control of refresh driver
|
||||
SpecialPowers.DOMWindowUtils.restoreNormalRefresh();
|
||||
}
|
||||
|
||||
function test_scroll_behavior_framerate() {
|
||||
/**
|
||||
* CSSOM-View scroll-behavior smooth scroll animations must produce the
|
||||
* same results indendently of frame-rate:
|
||||
*
|
||||
* - Reference samples of scroll position for each frame are captured from
|
||||
* a smooth scroll at 120fps for variations in X-Distance, Y-Distance.
|
||||
* - Test samples are captured from an animation with the same parameters
|
||||
* at varying framerates.
|
||||
* - Variance in position at each sampled interval is compared to the
|
||||
* 120fps reference. To pass the test, the position of each test
|
||||
* sample must match the reference position with a tolerance of one test
|
||||
* sample frame's range of motion. This range of motion is calculated
|
||||
* by the position delta of the reference samples one test frame duration
|
||||
* before and after.
|
||||
* - The duration of the reference sample animation and the test sample
|
||||
* animation must match within 1 frame to pass the test.
|
||||
* - The simulation driving the animation must converge and stop on the
|
||||
* destination position for the test to pass.
|
||||
*/
|
||||
|
||||
// Use 120hz for reference samples
|
||||
var REFERENCE_FRAME_RATE = 120;
|
||||
|
||||
var frame_rates = [ 5, 30, 60 ];
|
||||
var deltas = [ 0, 1, 100, -100, 50000 ];
|
||||
|
||||
deltas.forEach(function(delta_x) {
|
||||
deltas.forEach(function(delta_y) {
|
||||
// start_x and start_y must be at least as big as the greatest negative
|
||||
// number in the deltas array in order to prevent the animation from
|
||||
// being interrupted by scroll range boundaries.
|
||||
var start_x = 1000;
|
||||
var start_y = 1000;
|
||||
var end_x = start_x + delta_x;
|
||||
var end_y = start_y + delta_y;
|
||||
var reference_time_step = Math.floor(1000 / REFERENCE_FRAME_RATE);
|
||||
|
||||
var ref_samples = sample_animation(start_x, start_y,
|
||||
end_x, end_y,
|
||||
reference_time_step);
|
||||
|
||||
var reference_duration = ref_samples.length * reference_time_step; // ms
|
||||
|
||||
frame_rates.forEach(function(frame_rate) {
|
||||
var test_time_step = Math.floor(1000 / frame_rate);
|
||||
|
||||
var test_samples = sample_animation(start_x, start_y, end_x, end_y,
|
||||
test_time_step);
|
||||
|
||||
var test_duration = test_samples.length * test_time_step; // ms
|
||||
|
||||
// Variance in duration of animation must be accurate to within one
|
||||
// frame interval
|
||||
var duration_variance = Math.max(0, Math.abs(test_duration - reference_duration) - test_time_step);
|
||||
is(duration_variance, 0, 'Smooth scroll animation duration must not '
|
||||
+ 'be framerate dependent at delta_x: ' + delta_x + ', delta_y: '
|
||||
+ delta_y + ', frame_rate: ' + frame_rate + 'fps');
|
||||
|
||||
var max_variance = 0;
|
||||
test_samples.forEach(function(sample, sample_index) {
|
||||
|
||||
var test_to_ref = ref_samples.length / test_samples.length;
|
||||
var ref_index_this_frame = clamp(Math.floor(sample_index * test_to_ref),
|
||||
0, ref_samples.length - 1);
|
||||
var ref_index_prev_frame = clamp(Math.floor((sample_index - 1) * test_to_ref),
|
||||
0, ref_samples.length - 1);
|
||||
var ref_index_next_frame = clamp(Math.floor((sample_index + 1) * test_to_ref),
|
||||
0, ref_samples.length - 1);
|
||||
|
||||
var ref_sample_this_frame = ref_samples[ref_index_this_frame];
|
||||
var ref_sample_prev_frame = ref_samples[ref_index_prev_frame];
|
||||
var ref_sample_next_frame = ref_samples[ref_index_next_frame];
|
||||
|
||||
var ref_x_min = Math.min(ref_sample_prev_frame[0],
|
||||
ref_sample_this_frame[0],
|
||||
ref_sample_next_frame[0]);
|
||||
|
||||
var ref_y_min = Math.min(ref_sample_prev_frame[1],
|
||||
ref_sample_this_frame[1],
|
||||
ref_sample_next_frame[1]);
|
||||
|
||||
var ref_x_max = Math.max(ref_sample_prev_frame[0],
|
||||
ref_sample_this_frame[0],
|
||||
ref_sample_next_frame[0]);
|
||||
|
||||
var ref_y_max = Math.max(ref_sample_prev_frame[1],
|
||||
ref_sample_this_frame[1],
|
||||
ref_sample_next_frame[1]);
|
||||
|
||||
// Varience is expected to be at most 1 pixel beyond the range,
|
||||
// due to integer rounding of pixel position.
|
||||
var POSITION_TOLERANCE = 1; // 1 pixel
|
||||
|
||||
max_variance = Math.max(max_variance,
|
||||
ref_x_min - sample[0] - POSITION_TOLERANCE,
|
||||
sample[0] - ref_x_max - POSITION_TOLERANCE,
|
||||
ref_y_min - sample[1] - POSITION_TOLERANCE,
|
||||
sample[1] - ref_y_max - POSITION_TOLERANCE);
|
||||
});
|
||||
is(max_variance, 0, 'Smooth scroll animated position must not be '
|
||||
+ 'framerate dependent at delta_x: ' + delta_x + ', delta_y: '
|
||||
+ delta_y + ', frame_rate: ' + frame_rate + 'fps');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function sample_animation(start_x, start_y, end_x, end_y, time_step) {
|
||||
// The animation must be stopped at the destination position for
|
||||
// MIN_STOPPED_FRAMES consecutive frames to detect that the animation has
|
||||
// completed.
|
||||
var MIN_STOPPED_FRAMES = 15; // 15 frames
|
||||
|
||||
// In case the simulation fails to converge, the test will time out after
|
||||
// processing MAX_TIME milliseconds of animation.
|
||||
var MAX_TIME = 10000; // 10 seconds
|
||||
|
||||
// Take control of refresh driver so we can synthesize
|
||||
// various frame rates
|
||||
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(0);
|
||||
|
||||
var position_samples = [];
|
||||
|
||||
var frame_count_at_destination = 0;
|
||||
|
||||
window.scrollTo(start_x, start_y);
|
||||
window.scrollTo(end_x, end_y, {behavior: 'smooth'});
|
||||
|
||||
var current_time = 0; // ms
|
||||
var ref_samples = [];
|
||||
while (current_time < MAX_TIME && frame_count_at_destination < 15) {
|
||||
|
||||
position_samples.push([window.scrollX, window.scrollY]);
|
||||
|
||||
current_time += time_step;
|
||||
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(time_step);
|
||||
|
||||
if (window.scrollX == end_x && window.scrollY == end_y) {
|
||||
frame_count_at_destination++;
|
||||
} else {
|
||||
frame_count_at_destination = 0;
|
||||
}
|
||||
}
|
||||
|
||||
isnot(frame_count_at_destination, 0,
|
||||
'Smooth scrolls must always end at their destination '
|
||||
+ 'unless they are interrupted, at delta_x: ' + (end_x - start_x)
|
||||
+ ', delta_y: ' + (end_y - start_y));
|
||||
|
||||
window.scrollTo(0, 0);
|
||||
|
||||
// Release control of refresh driver
|
||||
SpecialPowers.DOMWindowUtils.restoreNormalRefresh();
|
||||
|
||||
// We must not include the duplicated frames at the animation destination
|
||||
// as the tests are dependant on the total duration of the animation to
|
||||
// be accurate.
|
||||
position_samples.splice(1 - MIN_STOPPED_FRAMES, MIN_STOPPED_FRAMES - 1);
|
||||
|
||||
return position_samples;
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<div id="scroll_behavior_test_body">
|
||||
<div id="scroll_to_target" class="scroll_to_target"></div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user