mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-04 22:37:29 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
261
gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
Normal file
261
gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
// Utilities for synthesizing of native events.
|
||||
|
||||
function getPlatform() {
|
||||
if (navigator.platform.indexOf("Win") == 0) {
|
||||
return "windows";
|
||||
}
|
||||
if (navigator.platform.indexOf("Mac") == 0) {
|
||||
return "mac";
|
||||
}
|
||||
// Check for Android before Linux
|
||||
if (navigator.appVersion.indexOf("Android") >= 0) {
|
||||
return "android"
|
||||
}
|
||||
if (navigator.platform.indexOf("Linux") == 0) {
|
||||
return "linux";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
function nativeVerticalWheelEventMsg() {
|
||||
switch (getPlatform()) {
|
||||
case "windows": return 0x020A; // WM_MOUSEWHEEL
|
||||
case "mac": return 0; // value is unused, can be anything
|
||||
case "linux": return 4; // value is unused, pass GDK_SCROLL_SMOOTH anyway
|
||||
}
|
||||
throw "Native wheel events not supported on platform " + getPlatform();
|
||||
}
|
||||
|
||||
function nativeHorizontalWheelEventMsg() {
|
||||
switch (getPlatform()) {
|
||||
case "windows": return 0x020E; // WM_MOUSEHWHEEL
|
||||
case "mac": return 0; // value is unused, can be anything
|
||||
case "linux": return 4; // value is unused, pass GDK_SCROLL_SMOOTH anyway
|
||||
}
|
||||
throw "Native wheel events not supported on platform " + getPlatform();
|
||||
}
|
||||
|
||||
// Given a pixel scrolling delta, converts it to the platform's native units.
|
||||
function nativeScrollUnits(aElement, aDimen) {
|
||||
switch (getPlatform()) {
|
||||
case "linux": {
|
||||
// GTK deltas are treated as line height divided by 3 by gecko.
|
||||
var targetWindow = aElement.ownerDocument.defaultView;
|
||||
var lineHeight = targetWindow.getComputedStyle(aElement)["font-size"];
|
||||
return aDimen / (parseInt(lineHeight) * 3);
|
||||
}
|
||||
}
|
||||
return aDimen;
|
||||
}
|
||||
|
||||
function nativeMouseDownEventMsg() {
|
||||
switch (getPlatform()) {
|
||||
case "windows": return 2; // MOUSEEVENTF_LEFTDOWN
|
||||
case "mac": return 1; // NSLeftMouseDown
|
||||
case "linux": return 4; // GDK_BUTTON_PRESS
|
||||
case "android": return 5; // ACTION_POINTER_DOWN
|
||||
}
|
||||
throw "Native mouse-down events not supported on platform " + getPlatform();
|
||||
}
|
||||
|
||||
function nativeMouseMoveEventMsg() {
|
||||
switch (getPlatform()) {
|
||||
case "windows": return 1; // MOUSEEVENTF_MOVE
|
||||
case "mac": return 5; // NSMouseMoved
|
||||
case "linux": return 3; // GDK_MOTION_NOTIFY
|
||||
case "android": return 7; // ACTION_HOVER_MOVE
|
||||
}
|
||||
throw "Native mouse-move events not supported on platform " + getPlatform();
|
||||
}
|
||||
|
||||
function nativeMouseUpEventMsg() {
|
||||
switch (getPlatform()) {
|
||||
case "windows": return 4; // MOUSEEVENTF_LEFTUP
|
||||
case "mac": return 2; // NSLeftMouseUp
|
||||
case "linux": return 7; // GDK_BUTTON_RELEASE
|
||||
case "android": return 6; // ACTION_POINTER_UP
|
||||
}
|
||||
throw "Native mouse-up events not supported on platform " + getPlatform();
|
||||
}
|
||||
|
||||
// Convert (aX, aY), in CSS pixels relative to aElement's bounding rect,
|
||||
// to device pixels relative to the screen.
|
||||
function coordinatesRelativeToScreen(aX, aY, aElement) {
|
||||
var targetWindow = aElement.ownerDocument.defaultView;
|
||||
var scale = targetWindow.devicePixelRatio;
|
||||
var rect = aElement.getBoundingClientRect();
|
||||
return {
|
||||
x: (targetWindow.mozInnerScreenX + rect.left + aX) * scale,
|
||||
y: (targetWindow.mozInnerScreenY + rect.top + aY) * scale
|
||||
};
|
||||
}
|
||||
|
||||
// Get the bounding box of aElement, and return it in device pixels
|
||||
// relative to the screen.
|
||||
function rectRelativeToScreen(aElement) {
|
||||
var targetWindow = aElement.ownerDocument.defaultView;
|
||||
var scale = targetWindow.devicePixelRatio;
|
||||
var rect = aElement.getBoundingClientRect();
|
||||
return {
|
||||
x: (targetWindow.mozInnerScreenX + rect.left) * scale,
|
||||
y: (targetWindow.mozInnerScreenY + rect.top) * scale,
|
||||
w: (rect.width * scale),
|
||||
h: (rect.height * scale)
|
||||
};
|
||||
}
|
||||
|
||||
// Synthesizes a native mousewheel event and returns immediately. This does not
|
||||
// guarantee anything; you probably want to use one of the other functions below
|
||||
// which actually wait for results.
|
||||
// aX and aY are relative to the top-left of |aElement|'s containing window.
|
||||
// aDeltaX and aDeltaY are pixel deltas, and aObserver can be left undefined
|
||||
// if not needed.
|
||||
function synthesizeNativeWheel(aElement, aX, aY, aDeltaX, aDeltaY, aObserver) {
|
||||
var pt = coordinatesRelativeToScreen(aX, aY, aElement);
|
||||
if (aDeltaX && aDeltaY) {
|
||||
throw "Simultaneous wheeling of horizontal and vertical is not supported on all platforms.";
|
||||
}
|
||||
aDeltaX = nativeScrollUnits(aElement, aDeltaX);
|
||||
aDeltaY = nativeScrollUnits(aElement, aDeltaY);
|
||||
var msg = aDeltaX ? nativeHorizontalWheelEventMsg() : nativeVerticalWheelEventMsg();
|
||||
var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView);
|
||||
utils.sendNativeMouseScrollEvent(pt.x, pt.y, msg, aDeltaX, aDeltaY, 0, 0, 0, aElement, aObserver);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Synthesizes a native mousewheel event and invokes the callback once the
|
||||
// request has been successfully made to the OS. This does not necessarily
|
||||
// guarantee that the OS generates the event we requested. See
|
||||
// synthesizeNativeWheel for details on the parameters.
|
||||
function synthesizeNativeWheelAndWaitForObserver(aElement, aX, aY, aDeltaX, aDeltaY, aCallback) {
|
||||
var observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aCallback && aTopic == "mousescrollevent") {
|
||||
setTimeout(aCallback, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
return synthesizeNativeWheel(aElement, aX, aY, aDeltaX, aDeltaY, observer);
|
||||
}
|
||||
|
||||
// Synthesizes a native mousewheel event and invokes the callback once the
|
||||
// wheel event is dispatched to |aElement|'s containing window. If the event
|
||||
// targets content in a subdocument, |aElement| should be inside the
|
||||
// subdocument. See synthesizeNativeWheel for details on the other parameters.
|
||||
function synthesizeNativeWheelAndWaitForWheelEvent(aElement, aX, aY, aDeltaX, aDeltaY, aCallback) {
|
||||
var targetWindow = aElement.ownerDocument.defaultView;
|
||||
targetWindow.addEventListener("wheel", function wheelWaiter(e) {
|
||||
targetWindow.removeEventListener("wheel", wheelWaiter);
|
||||
setTimeout(aCallback, 0);
|
||||
});
|
||||
return synthesizeNativeWheel(aElement, aX, aY, aDeltaX, aDeltaY);
|
||||
}
|
||||
|
||||
// Synthesizes a native mousewheel event and invokes the callback once the
|
||||
// first resulting scroll event is dispatched to |aElement|'s containing window.
|
||||
// If the event targets content in a subdocument, |aElement| should be inside
|
||||
// the subdocument. See synthesizeNativeWheel for details on the other
|
||||
// parameters.
|
||||
function synthesizeNativeWheelAndWaitForScrollEvent(aElement, aX, aY, aDeltaX, aDeltaY, aCallback) {
|
||||
var targetWindow = aElement.ownerDocument.defaultView;
|
||||
var useCapture = true; // scroll events don't always bubble
|
||||
targetWindow.addEventListener("scroll", function scrollWaiter(e) {
|
||||
targetWindow.removeEventListener("scroll", scrollWaiter, useCapture);
|
||||
setTimeout(aCallback, 0);
|
||||
}, useCapture);
|
||||
return synthesizeNativeWheel(aElement, aX, aY, aDeltaX, aDeltaY);
|
||||
}
|
||||
|
||||
// Synthesizes a native mouse move event and returns immediately.
|
||||
// aX and aY are relative to the top-left of |aElement|'s containing window.
|
||||
function synthesizeNativeMouseMove(aElement, aX, aY) {
|
||||
var pt = coordinatesRelativeToScreen(aX, aY, aElement);
|
||||
var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView);
|
||||
utils.sendNativeMouseEvent(pt.x, pt.y, nativeMouseMoveEventMsg(), 0, aElement);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Synthesizes a native mouse move event and invokes the callback once the
|
||||
// mouse move event is dispatched to |aElement|'s containing window. If the event
|
||||
// targets content in a subdocument, |aElement| should be inside the
|
||||
// subdocument. See synthesizeNativeMouseMove for details on the other
|
||||
// parameters.
|
||||
function synthesizeNativeMouseMoveAndWaitForMoveEvent(aElement, aX, aY, aCallback) {
|
||||
var targetWindow = aElement.ownerDocument.defaultView;
|
||||
targetWindow.addEventListener("mousemove", function mousemoveWaiter(e) {
|
||||
targetWindow.removeEventListener("mousemove", mousemoveWaiter);
|
||||
setTimeout(aCallback, 0);
|
||||
});
|
||||
return synthesizeNativeMouseMove(aElement, aX, aY);
|
||||
}
|
||||
|
||||
// Synthesizes a native touch event and dispatches it. aX and aY in CSS pixels
|
||||
// relative to the top-left of |aElement|'s bounding rect.
|
||||
function synthesizeNativeTouch(aElement, aX, aY, aType, aObserver = null, aTouchId = 0) {
|
||||
var pt = coordinatesRelativeToScreen(aX, aY, aElement);
|
||||
var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView);
|
||||
utils.sendNativeTouchPoint(aTouchId, aType, pt.x, pt.y, 1, 90, aObserver);
|
||||
return true;
|
||||
}
|
||||
|
||||
// A handy constant when synthesizing native touch drag events with the pref
|
||||
// "apz.touch_start_tolerance" set to 0. In this case, the first touchmove with
|
||||
// a nonzero pixel movement is consumed by the APZ to transition from the
|
||||
// "touching" state to the "panning" state, so calls to synthesizeNativeTouchDrag
|
||||
// should add an extra pixel pixel for this purpose. The TOUCH_SLOP provides
|
||||
// a constant that can be used for this purpose. Note that if the touch start
|
||||
// tolerance is set to something higher, the touch slop amount used must be
|
||||
// correspondingly increased so as to be higher than the tolerance.
|
||||
const TOUCH_SLOP = 1;
|
||||
function synthesizeNativeTouchDrag(aElement, aX, aY, aDeltaX, aDeltaY, aObserver = null, aTouchId = 0) {
|
||||
synthesizeNativeTouch(aElement, aX, aY, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, null, aTouchId);
|
||||
var steps = Math.max(Math.abs(aDeltaX), Math.abs(aDeltaY));
|
||||
for (var i = 1; i < steps; i++) {
|
||||
var dx = i * (aDeltaX / steps);
|
||||
var dy = i * (aDeltaY / steps);
|
||||
synthesizeNativeTouch(aElement, aX + dx, aY + dy, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, null, aTouchId);
|
||||
}
|
||||
synthesizeNativeTouch(aElement, aX + aDeltaX, aY + aDeltaY, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, null, aTouchId);
|
||||
return synthesizeNativeTouch(aElement, aX + aDeltaX, aY + aDeltaY, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, aObserver, aTouchId);
|
||||
}
|
||||
|
||||
function synthesizeNativeTap(aElement, aX, aY, aObserver = null) {
|
||||
var pt = coordinatesRelativeToScreen(aX, aY, aElement);
|
||||
var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView);
|
||||
utils.sendNativeTouchTap(pt.x, pt.y, false, aObserver);
|
||||
return true;
|
||||
}
|
||||
|
||||
function synthesizeNativeMouseEvent(aElement, aX, aY, aType, aObserver = null) {
|
||||
var pt = coordinatesRelativeToScreen(aX, aY, aElement);
|
||||
var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView);
|
||||
utils.sendNativeMouseEvent(pt.x, pt.y, aType, 0, aElement, aObserver);
|
||||
return true;
|
||||
}
|
||||
|
||||
function synthesizeNativeClick(aElement, aX, aY, aObserver = null) {
|
||||
var pt = coordinatesRelativeToScreen(aX, aY, aElement);
|
||||
var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView);
|
||||
utils.sendNativeMouseEvent(pt.x, pt.y, nativeMouseDownEventMsg(), 0, aElement, function() {
|
||||
utils.sendNativeMouseEvent(pt.x, pt.y, nativeMouseUpEventMsg(), 0, aElement, aObserver);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
// Move the mouse to (dx, dy) relative to |element|, and scroll the wheel
|
||||
// at that location.
|
||||
// Moving the mouse is necessary to avoid wheel events from two consecutive
|
||||
// moveMouseAndScrollWheelOver() calls on different elements being incorrectly
|
||||
// considered as part of the same wheel transaction.
|
||||
// We also wait for the mouse move event to be processed before sending the
|
||||
// wheel event, otherwise there is a chance they might get reordered, and
|
||||
// we have the transaction problem again.
|
||||
function moveMouseAndScrollWheelOver(element, dx, dy, testDriver, waitForScroll = true) {
|
||||
return synthesizeNativeMouseMoveAndWaitForMoveEvent(element, dx, dy, function() {
|
||||
if (waitForScroll) {
|
||||
synthesizeNativeWheelAndWaitForScrollEvent(element, dx, dy, 0, -10, testDriver);
|
||||
} else {
|
||||
synthesizeNativeWheelAndWaitForWheelEvent(element, dx, dy, 0, -10, testDriver);
|
||||
}
|
||||
});
|
||||
}
|
||||
403
gfx/layers/apz/test/mochitest/apz_test_utils.js
Normal file
403
gfx/layers/apz/test/mochitest/apz_test_utils.js
Normal file
|
|
@ -0,0 +1,403 @@
|
|||
// Utilities for writing APZ tests using the framework added in bug 961289
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Functions that convert the APZ test data into a more usable form.
|
||||
// Every place we have a WebIDL sequence whose elements are dictionaries
|
||||
// with two elements, a key, and a value, we convert this into a JS
|
||||
// object with a property for each key/value pair. (This is the structure
|
||||
// we really want, but we can't express in directly in WebIDL.)
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
function convertEntries(entries) {
|
||||
var result = {};
|
||||
for (var i = 0; i < entries.length; ++i) {
|
||||
result[entries[i].key] = entries[i].value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getPropertyAsRect(scrollFrames, scrollId, prop) {
|
||||
SimpleTest.ok(scrollId in scrollFrames,
|
||||
'expected scroll frame data for scroll id ' + scrollId);
|
||||
var scrollFrameData = scrollFrames[scrollId];
|
||||
SimpleTest.ok('displayport' in scrollFrameData,
|
||||
'expected a ' + prop + ' for scroll id ' + scrollId);
|
||||
var value = scrollFrameData[prop];
|
||||
var pieces = value.replace(/[()\s]+/g, '').split(',');
|
||||
SimpleTest.is(pieces.length, 4, "expected string of form (x,y,w,h)");
|
||||
return { x: parseInt(pieces[0]),
|
||||
y: parseInt(pieces[1]),
|
||||
w: parseInt(pieces[2]),
|
||||
h: parseInt(pieces[3]) };
|
||||
}
|
||||
|
||||
function convertScrollFrameData(scrollFrames) {
|
||||
var result = {};
|
||||
for (var i = 0; i < scrollFrames.length; ++i) {
|
||||
result[scrollFrames[i].scrollId] = convertEntries(scrollFrames[i].entries);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function convertBuckets(buckets) {
|
||||
var result = {};
|
||||
for (var i = 0; i < buckets.length; ++i) {
|
||||
result[buckets[i].sequenceNumber] = convertScrollFrameData(buckets[i].scrollFrames);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function convertTestData(testData) {
|
||||
var result = {};
|
||||
result.paints = convertBuckets(testData.paints);
|
||||
result.repaintRequests = convertBuckets(testData.repaintRequests);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Given APZ test data for a single paint on the compositor side,
|
||||
// reconstruct the APZC tree structure from the 'parentScrollId'
|
||||
// entries that were logged. More specifically, the subset of the
|
||||
// APZC tree structure corresponding to the layer subtree for the
|
||||
// content process that triggered the paint, is reconstructed (as
|
||||
// the APZ test data only contains information abot this subtree).
|
||||
function buildApzcTree(paint) {
|
||||
// The APZC tree can potentially have multiple root nodes,
|
||||
// so we invent a node that is the parent of all roots.
|
||||
// This 'root' does not correspond to an APZC.
|
||||
var root = {scrollId: -1, children: []};
|
||||
for (var scrollId in paint) {
|
||||
paint[scrollId].children = [];
|
||||
paint[scrollId].scrollId = scrollId;
|
||||
}
|
||||
for (var scrollId in paint) {
|
||||
var parentNode = null;
|
||||
if ("hasNoParentWithSameLayersId" in paint[scrollId]) {
|
||||
parentNode = root;
|
||||
} else if ("parentScrollId" in paint[scrollId]) {
|
||||
parentNode = paint[paint[scrollId].parentScrollId];
|
||||
}
|
||||
parentNode.children.push(paint[scrollId]);
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
// Given an APZC tree produced by buildApzcTree, return the RCD node in
|
||||
// the tree, or null if there was none.
|
||||
function findRcdNode(apzcTree) {
|
||||
if (!!apzcTree.isRootContent) { // isRootContent will be undefined or "1"
|
||||
return apzcTree;
|
||||
}
|
||||
for (var i = 0; i < apzcTree.children.length; i++) {
|
||||
var rcd = findRcdNode(apzcTree.children[i]);
|
||||
if (rcd != null) {
|
||||
return rcd;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Return whether an element whose id includes |elementId| has been layerized.
|
||||
// Assumes |elementId| will be present in the content description for the
|
||||
// element, and not in the content descriptions of other elements.
|
||||
function isLayerized(elementId) {
|
||||
var contentTestData = SpecialPowers.getDOMWindowUtils(window).getContentAPZTestData();
|
||||
ok(contentTestData.paints.length > 0, "expected at least one paint");
|
||||
var seqno = contentTestData.paints[contentTestData.paints.length - 1].sequenceNumber;
|
||||
contentTestData = convertTestData(contentTestData);
|
||||
var paint = contentTestData.paints[seqno];
|
||||
for (var scrollId in paint) {
|
||||
if ("contentDescription" in paint[scrollId]) {
|
||||
if (paint[scrollId]["contentDescription"].includes(elementId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function flushApzRepaints(aCallback, aWindow = window) {
|
||||
if (!aCallback) {
|
||||
throw "A callback must be provided!";
|
||||
}
|
||||
var repaintDone = function() {
|
||||
SpecialPowers.Services.obs.removeObserver(repaintDone, "apz-repaints-flushed", false);
|
||||
setTimeout(aCallback, 0);
|
||||
};
|
||||
SpecialPowers.Services.obs.addObserver(repaintDone, "apz-repaints-flushed", false);
|
||||
if (SpecialPowers.getDOMWindowUtils(aWindow).flushApzRepaints()) {
|
||||
dump("Flushed APZ repaints, waiting for callback...\n");
|
||||
} else {
|
||||
dump("Flushing APZ repaints was a no-op, triggering callback directly...\n");
|
||||
repaintDone();
|
||||
}
|
||||
}
|
||||
|
||||
// Flush repaints, APZ pending repaints, and any repaints resulting from that
|
||||
// flush. This is particularly useful if the test needs to reach some sort of
|
||||
// "idle" state in terms of repaints. Usually just doing waitForAllPaints
|
||||
// followed by flushApzRepaints is sufficient to flush all APZ state back to
|
||||
// the main thread, but it can leave a paint scheduled which will get triggered
|
||||
// at some later time. For tests that specifically test for painting at
|
||||
// specific times, this method is the way to go. Even if in doubt, this is the
|
||||
// preferred method as the extra step is "safe" and shouldn't interfere with
|
||||
// most tests.
|
||||
function waitForApzFlushedRepaints(aCallback) {
|
||||
// First flush the main-thread paints and send transactions to the APZ
|
||||
waitForAllPaints(function() {
|
||||
// Then flush the APZ to make sure any repaint requests have been sent
|
||||
// back to the main thread
|
||||
flushApzRepaints(function() {
|
||||
// Then flush the main-thread again to process the repaint requests.
|
||||
// Once this is done, we should be in a stable state with nothing
|
||||
// pending, so we can trigger the callback.
|
||||
waitForAllPaints(aCallback);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// This function takes a set of subtests to run one at a time in new top-level
|
||||
// windows, and returns a Promise that is resolved once all the subtests are
|
||||
// done running.
|
||||
//
|
||||
// The aSubtests array is an array of objects with the following keys:
|
||||
// file: required, the filename of the subtest.
|
||||
// prefs: optional, an array of arrays containing key-value prefs to set.
|
||||
// dp_suppression: optional, a boolean on whether or not to respect displayport
|
||||
// suppression during the test.
|
||||
// onload: optional, a function that will be registered as a load event listener
|
||||
// for the child window that will hold the subtest. the function will be
|
||||
// passed exactly one argument, which will be the child window.
|
||||
// An example of an array is:
|
||||
// aSubtests = [
|
||||
// { 'file': 'test_file_name.html' },
|
||||
// { 'file': 'test_file_2.html', 'prefs': [['pref.name', true], ['other.pref', 1000]], 'dp_suppression': false }
|
||||
// { 'file': 'file_3.html', 'onload': function(w) { w.subtestDone(); } }
|
||||
// ];
|
||||
//
|
||||
// Each subtest should call the subtestDone() function when it is done, to
|
||||
// indicate that the window should be torn down and the next text should run.
|
||||
// The subtestDone() function is injected into the subtest's window by this
|
||||
// function prior to loading the subtest. For convenience, the |is| and |ok|
|
||||
// functions provided by SimpleTest are also mapped into the subtest's window.
|
||||
// For other things from the parent, the subtest can use window.opener.<whatever>
|
||||
// to access objects.
|
||||
function runSubtestsSeriallyInFreshWindows(aSubtests) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var testIndex = -1;
|
||||
var w = null;
|
||||
|
||||
function advanceSubtestExecution() {
|
||||
var test = aSubtests[testIndex];
|
||||
if (w) {
|
||||
if (typeof test.dp_suppression != 'undefined') {
|
||||
// We modified the suppression when starting the test, so now undo that.
|
||||
SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(!test.dp_suppression);
|
||||
}
|
||||
if (test.prefs) {
|
||||
// We pushed some prefs for this test, pop them, and re-invoke
|
||||
// advanceSubtestExecution() after that's been processed
|
||||
SpecialPowers.popPrefEnv(function() {
|
||||
w.close();
|
||||
w = null;
|
||||
advanceSubtestExecution();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
w.close();
|
||||
}
|
||||
|
||||
testIndex++;
|
||||
if (testIndex >= aSubtests.length) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
test = aSubtests[testIndex];
|
||||
if (typeof test.dp_suppression != 'undefined') {
|
||||
// Normally during a test, the displayport will get suppressed during page
|
||||
// load, and unsuppressed at a non-deterministic time during the test. The
|
||||
// unsuppression can trigger a repaint which interferes with the test, so
|
||||
// to avoid that we can force the displayport to be unsuppressed for the
|
||||
// entire test which is more deterministic.
|
||||
SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(test.dp_suppression);
|
||||
}
|
||||
|
||||
function spawnTest(aFile) {
|
||||
w = window.open('', "_blank");
|
||||
w.subtestDone = advanceSubtestExecution;
|
||||
w.SimpleTest = SimpleTest;
|
||||
w.is = function(a, b, msg) { return is(a, b, aFile + " | " + msg); };
|
||||
w.ok = function(cond, name, diag) { return ok(cond, aFile + " | " + name, diag); };
|
||||
if (test.onload) {
|
||||
w.addEventListener('load', function(e) { test.onload(w); }, { once: true });
|
||||
}
|
||||
w.location = location.href.substring(0, location.href.lastIndexOf('/') + 1) + aFile;
|
||||
return w;
|
||||
}
|
||||
|
||||
if (test.prefs) {
|
||||
// Got some prefs for this subtest, push them
|
||||
SpecialPowers.pushPrefEnv({"set": test.prefs}, function() {
|
||||
w = spawnTest(test.file);
|
||||
});
|
||||
} else {
|
||||
w = spawnTest(test.file);
|
||||
}
|
||||
}
|
||||
|
||||
advanceSubtestExecution();
|
||||
});
|
||||
}
|
||||
|
||||
function pushPrefs(prefs) {
|
||||
return SpecialPowers.pushPrefEnv({'set': prefs});
|
||||
}
|
||||
|
||||
function waitUntilApzStable() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
SimpleTest.waitForFocus(function() {
|
||||
waitForAllPaints(function() {
|
||||
flushApzRepaints(resolve);
|
||||
});
|
||||
}, window);
|
||||
});
|
||||
}
|
||||
|
||||
function isApzEnabled() {
|
||||
var enabled = SpecialPowers.getDOMWindowUtils(window).asyncPanZoomEnabled;
|
||||
if (!enabled) {
|
||||
// All tests are required to have at least one assertion. Since APZ is
|
||||
// disabled, and the main test is presumably not going to run, we stick in
|
||||
// a dummy assertion here to keep the test passing.
|
||||
SimpleTest.ok(true, "APZ is not enabled; this test will be skipped");
|
||||
}
|
||||
return enabled;
|
||||
}
|
||||
|
||||
// Despite what this function name says, this does not *directly* run the
|
||||
// provided continuation testFunction. Instead, it returns a function that
|
||||
// can be used to run the continuation. The extra level of indirection allows
|
||||
// it to be more easily added to a promise chain, like so:
|
||||
// waitUntilApzStable().then(runContinuation(myTest));
|
||||
//
|
||||
// If you want to run the continuation directly, outside of a promise chain,
|
||||
// you can invoke the return value of this function, like so:
|
||||
// runContinuation(myTest)();
|
||||
function runContinuation(testFunction) {
|
||||
// We need to wrap this in an extra function, so that the call site can
|
||||
// be more readable without running the promise too early. In other words,
|
||||
// if we didn't have this extra function, the promise would start running
|
||||
// during construction of the promise chain, concurrently with the first
|
||||
// promise in the chain.
|
||||
return function() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var testContinuation = null;
|
||||
|
||||
function driveTest() {
|
||||
if (!testContinuation) {
|
||||
testContinuation = testFunction(driveTest);
|
||||
}
|
||||
var ret = testContinuation.next();
|
||||
if (ret.done) {
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
|
||||
driveTest();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// Take a snapshot of the given rect, *including compositor transforms* (i.e.
|
||||
// includes async scroll transforms applied by APZ). If you don't need the
|
||||
// compositor transforms, you can probably get away with using
|
||||
// SpecialPowers.snapshotWindowWithOptions or one of the friendlier wrappers.
|
||||
// The rect provided is expected to be relative to the screen, for example as
|
||||
// returned by rectRelativeToScreen in apz_test_native_event_utils.js.
|
||||
// Example usage:
|
||||
// var snapshot = getSnapshot(rectRelativeToScreen(myDiv));
|
||||
// which will take a snapshot of the 'myDiv' element. Note that if part of the
|
||||
// element is obscured by other things on top, the snapshot will include those
|
||||
// things. If it is clipped by a scroll container, the snapshot will include
|
||||
// that area anyway, so you will probably get parts of the scroll container in
|
||||
// the snapshot. If the rect extends outside the browser window then the
|
||||
// results are undefined.
|
||||
// The snapshot is returned in the form of a data URL.
|
||||
function getSnapshot(rect) {
|
||||
function parentProcessSnapshot() {
|
||||
addMessageListener('snapshot', function(rect) {
|
||||
Components.utils.import('resource://gre/modules/Services.jsm');
|
||||
var topWin = Services.wm.getMostRecentWindow('navigator:browser');
|
||||
|
||||
// reposition the rect relative to the top-level browser window
|
||||
rect = JSON.parse(rect);
|
||||
rect.x -= topWin.mozInnerScreenX;
|
||||
rect.y -= topWin.mozInnerScreenY;
|
||||
|
||||
// take the snapshot
|
||||
var canvas = topWin.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
canvas.width = rect.w;
|
||||
canvas.height = rect.h;
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.drawWindow(topWin, rect.x, rect.y, rect.w, rect.h, 'rgb(255,255,255)', ctx.DRAWWINDOW_DRAW_VIEW | ctx.DRAWWINDOW_USE_WIDGET_LAYERS | ctx.DRAWWINDOW_DRAW_CARET);
|
||||
return canvas.toDataURL();
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof getSnapshot.chromeHelper == 'undefined') {
|
||||
// This is the first time getSnapshot is being called; do initialization
|
||||
getSnapshot.chromeHelper = SpecialPowers.loadChromeScript(parentProcessSnapshot);
|
||||
SimpleTest.registerCleanupFunction(function() { getSnapshot.chromeHelper.destroy() });
|
||||
}
|
||||
|
||||
return getSnapshot.chromeHelper.sendSyncMessage('snapshot', JSON.stringify(rect)).toString();
|
||||
}
|
||||
|
||||
// Takes the document's query string and parses it, assuming the query string
|
||||
// is composed of key-value pairs where the value is in JSON format. The object
|
||||
// returned contains the various values indexed by their respective keys. In
|
||||
// case of duplicate keys, the last value be used.
|
||||
// Examples:
|
||||
// ?key="value"&key2=false&key3=500
|
||||
// produces { "key": "value", "key2": false, "key3": 500 }
|
||||
// ?key={"x":0,"y":50}&key2=[1,2,true]
|
||||
// produces { "key": { "x": 0, "y": 0 }, "key2": [1, 2, true] }
|
||||
function getQueryArgs() {
|
||||
var args = {};
|
||||
if (location.search.length > 0) {
|
||||
var params = location.search.substr(1).split('&');
|
||||
for (var p of params) {
|
||||
var [k, v] = p.split('=');
|
||||
args[k] = JSON.parse(v);
|
||||
}
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
// Return a function that returns a promise to create a script element with the
|
||||
// given URI and append it to the head of the document in the given window.
|
||||
// As with runContinuation(), the extra function wrapper is for convenience
|
||||
// at the call site, so that this can be chained with other promises:
|
||||
// waitUntilApzStable().then(injectScript('foo'))
|
||||
// .then(injectScript('bar'));
|
||||
// If you want to do the injection right away, run the function returned by
|
||||
// this function:
|
||||
// injectScript('foo')();
|
||||
function injectScript(aScript, aWindow = window) {
|
||||
return function() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var e = aWindow.document.createElement('script');
|
||||
e.type = 'text/javascript';
|
||||
e.onload = function() {
|
||||
resolve();
|
||||
};
|
||||
e.onerror = function() {
|
||||
dump('Script [' + aScript + '] errored out\n');
|
||||
reject();
|
||||
};
|
||||
e.src = aScript;
|
||||
aWindow.document.getElementsByTagName('head')[0].appendChild(e);
|
||||
});
|
||||
};
|
||||
}
|
||||
9
gfx/layers/apz/test/mochitest/chrome.ini
Normal file
9
gfx/layers/apz/test/mochitest/chrome.ini
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
apz_test_native_event_utils.js
|
||||
tags = apz-chrome
|
||||
|
||||
[test_smoothness.html]
|
||||
# hardware vsync only on win/mac
|
||||
# e10s only since APZ is only enabled on e10s
|
||||
skip-if = debug || (os != 'mac' && os != 'win') || !e10s
|
||||
38
gfx/layers/apz/test/mochitest/helper_basic_pan.html
Normal file
38
gfx/layers/apz/test/mochitest/helper_basic_pan.html
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Sanity panning test</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function scrollPage() {
|
||||
var transformEnd = function() {
|
||||
SpecialPowers.Services.obs.removeObserver(transformEnd, "APZ:TransformEnd", false);
|
||||
dump("Transform complete; flushing repaints...\n");
|
||||
flushApzRepaints(checkScroll);
|
||||
};
|
||||
SpecialPowers.Services.obs.addObserver(transformEnd, "APZ:TransformEnd", false);
|
||||
|
||||
synthesizeNativeTouchDrag(document.body, 10, 100, 0, -(50 + TOUCH_SLOP));
|
||||
dump("Finished native drag, waiting for transform-end observer...\n");
|
||||
}
|
||||
|
||||
function checkScroll() {
|
||||
is(window.scrollY, 50, "check that the window scrolled");
|
||||
subtestDone();
|
||||
}
|
||||
|
||||
waitUntilApzStable().then(scrollPage);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div style="height: 5000px; background-color: lightgreen;">
|
||||
This div makes the page scrollable.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
83
gfx/layers/apz/test/mochitest/helper_bug1151663.html
Normal file
83
gfx/layers/apz/test/mochitest/helper_bug1151663.html
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1151663
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1151663, helper page</title>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Infrastructure to get the test assertions to run at the right time.
|
||||
// -------------------------------------------------------------------
|
||||
var SimpleTest = window.opener.SimpleTest;
|
||||
|
||||
window.onload = function() {
|
||||
window.addEventListener("MozAfterPaint", afterPaint, false);
|
||||
};
|
||||
var utils = SpecialPowers.getDOMWindowUtils(window);
|
||||
function afterPaint(e) {
|
||||
// If there is another paint pending, wait for it.
|
||||
if (utils.isMozAfterPaintPending) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Once there are no more paints pending, remove the
|
||||
// MozAfterPaint listener and run the test logic.
|
||||
window.removeEventListener("MozAfterPaint", afterPaint, false);
|
||||
testBug1151663();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// The actual logic for testing bug 1151663.
|
||||
//
|
||||
// In this test we have a simple page which is scrollable, with a
|
||||
// scrollable <div> which is also scrollable. We test that the
|
||||
// <div> does not get an initial APZC, since primary scrollable
|
||||
// frame is the page's root scroll frame.
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
function testBug1151663() {
|
||||
// Get the content- and compositor-side test data from nsIDOMWindowUtils.
|
||||
var contentTestData = utils.getContentAPZTestData();
|
||||
var compositorTestData = utils.getCompositorAPZTestData();
|
||||
|
||||
// Get the sequence number of the last paint on the compositor side.
|
||||
// We do this before converting the APZ test data because the conversion
|
||||
// loses the order of the paints.
|
||||
SimpleTest.ok(compositorTestData.paints.length > 0,
|
||||
"expected at least one paint in compositor test data");
|
||||
var lastCompositorPaint = compositorTestData.paints[compositorTestData.paints.length - 1];
|
||||
var lastCompositorPaintSeqNo = lastCompositorPaint.sequenceNumber;
|
||||
|
||||
// Convert the test data into a representation that's easier to navigate.
|
||||
contentTestData = convertTestData(contentTestData);
|
||||
compositorTestData = convertTestData(compositorTestData);
|
||||
var paint = compositorTestData.paints[lastCompositorPaintSeqNo];
|
||||
|
||||
// Reconstruct the APZC tree structure in the last paint.
|
||||
var apzcTree = buildApzcTree(paint);
|
||||
|
||||
// The apzc tree for this page should consist of a single root APZC,
|
||||
// which either is the RCD with no child APZCs (e10s/B2G case) or has a
|
||||
// single child APZC which is for the RCD (fennec case).
|
||||
var rcd = findRcdNode(apzcTree);
|
||||
SimpleTest.ok(rcd != null, "found the RCD node");
|
||||
SimpleTest.is(rcd.children.length, 0, "expected no children on the RCD");
|
||||
|
||||
window.opener.finishTest();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body style="height: 500px; overflow: scroll">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1151663">Mozilla Bug 1151663</a>
|
||||
<div style="height: 50px; width: 50px; overflow: scroll">
|
||||
<!-- Put enough content into the subframe to make it have a nonzero scroll range -->
|
||||
<div style="height: 100px; width: 50px"></div>
|
||||
</div>
|
||||
<!-- Put enough content into the page to make it have a nonzero scroll range -->
|
||||
<div style="height: 1000px"></div>
|
||||
</body>
|
||||
</html>
|
||||
104
gfx/layers/apz/test/mochitest/helper_bug1162771.html
Normal file
104
gfx/layers/apz/test/mochitest/helper_bug1162771.html
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Test for touchend on media elements</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function* test(testDriver) {
|
||||
var v = document.getElementById('video');
|
||||
var a = document.getElementById('audio');
|
||||
var d = document.getElementById('div');
|
||||
|
||||
document.body.ontouchstart = function(e) {
|
||||
if (e.target === v || e.target === a || e.target === d) {
|
||||
e.target.style.display = 'none';
|
||||
ok(true, 'Set display to none on #' + e.target.id);
|
||||
} else {
|
||||
ok(false, 'Got unexpected touchstart on ' + e.target);
|
||||
}
|
||||
waitForAllPaints(testDriver);
|
||||
};
|
||||
|
||||
document.body.ontouchend = function(e) {
|
||||
if (e.target === v || e.target === a || e.target === d) {
|
||||
e.target._gotTouchend = true;
|
||||
ok(true, 'Got touchend event on #' + e.target.id);
|
||||
}
|
||||
testDriver();
|
||||
};
|
||||
|
||||
var utils = SpecialPowers.getDOMWindowUtils(window);
|
||||
|
||||
var pt = coordinatesRelativeToScreen(25, 5, v);
|
||||
yield utils.sendNativeTouchPoint(0, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, pt.x, pt.y, 1, 90, null);
|
||||
yield utils.sendNativeTouchPoint(0, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, pt.x, pt.y, 1, 90, null);
|
||||
ok(v._gotTouchend, 'Touchend was received on video element');
|
||||
|
||||
pt = coordinatesRelativeToScreen(25, 5, a);
|
||||
yield utils.sendNativeTouchPoint(0, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, pt.x, pt.y, 1, 90, null);
|
||||
yield utils.sendNativeTouchPoint(0, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, pt.x, pt.y, 1, 90, null);
|
||||
ok(a._gotTouchend, 'Touchend was received on audio element');
|
||||
|
||||
pt = coordinatesRelativeToScreen(25, 5, d);
|
||||
yield utils.sendNativeTouchPoint(0, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, pt.x, pt.y, 1, 90, null);
|
||||
yield utils.sendNativeTouchPoint(0, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, pt.x, pt.y, 1, 90, null);
|
||||
ok(d._gotTouchend, 'Touchend was received on div element');
|
||||
}
|
||||
|
||||
waitUntilApzStable()
|
||||
.then(runContinuation(test))
|
||||
.then(subtestDone);
|
||||
|
||||
</script>
|
||||
<style>
|
||||
* {
|
||||
font-size: 24px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#video {
|
||||
display:block;
|
||||
position:absolute;
|
||||
top: 100px;
|
||||
left:0;
|
||||
width: 33%;
|
||||
height: 100px;
|
||||
border:solid black 1px;
|
||||
background-color: #8a8;
|
||||
}
|
||||
|
||||
#audio {
|
||||
display:block;
|
||||
position:absolute;
|
||||
top: 100px;
|
||||
left:33%;
|
||||
width: 33%;
|
||||
height: 100px;
|
||||
border:solid black 1px;
|
||||
background-color: #a88;
|
||||
}
|
||||
|
||||
#div {
|
||||
display:block;
|
||||
position:absolute;
|
||||
top: 100px;
|
||||
left: 66%;
|
||||
width: 34%;
|
||||
height: 100px;
|
||||
border:solid black 1px;
|
||||
background-color: #88a;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Tap on the colored boxes to hide them.</p>
|
||||
<video id="video"></video>
|
||||
<audio id="audio" controls></audio>
|
||||
<div id="div"></div>
|
||||
</body>
|
||||
</html>
|
||||
574
gfx/layers/apz/test/mochitest/helper_bug1271432.html
Normal file
574
gfx/layers/apz/test/mochitest/helper_bug1271432.html
Normal file
|
|
@ -0,0 +1,574 @@
|
|||
<head>
|
||||
<title>Ensure that the hit region doesn't get unexpectedly expanded</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
function* test(testDriver) {
|
||||
var scroller = document.getElementById('scroller');
|
||||
var scrollerPos = scroller.scrollTop;
|
||||
var dx = 100, dy = 50;
|
||||
|
||||
is(window.scrollY, 0, "Initial page scroll position should be 0");
|
||||
is(scrollerPos, 0, "Initial scroller position should be 0");
|
||||
|
||||
yield moveMouseAndScrollWheelOver(scroller, dx, dy, testDriver);
|
||||
|
||||
is(window.scrollY, 0, "Page scroll position should still be 0");
|
||||
ok(scroller.scrollTop > scrollerPos, "Scroller should have scrolled");
|
||||
|
||||
// wait for it to layerize fully and then try again
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
scrollerPos = scroller.scrollTop;
|
||||
|
||||
yield moveMouseAndScrollWheelOver(scroller, dx, dy, testDriver);
|
||||
is(window.scrollY, 0, "Page scroll position should still be 0 after layerization");
|
||||
ok(scroller.scrollTop > scrollerPos, "Scroller should have continued scrolling");
|
||||
}
|
||||
|
||||
waitUntilApzStable()
|
||||
.then(runContinuation(test))
|
||||
.then(subtestDone);
|
||||
|
||||
</script>
|
||||
<style>
|
||||
a#with_after_content {
|
||||
background-color: #F16725;
|
||||
opacity: 0.8;
|
||||
display: inline-block;
|
||||
margin-top: 40px;
|
||||
margin-left: 40px;
|
||||
}
|
||||
a#with_after_content::after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
bottom: 40px;
|
||||
z-index: -1;
|
||||
right: 40px;
|
||||
background-color: transparent;
|
||||
border-style: solid;
|
||||
border-width: 15px 15px 15px 0;
|
||||
border-color: #d54e0e transparent transparent transparent;
|
||||
box-shadow: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
div#scroller {
|
||||
overflow-y: scroll;
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a id="with_after_content">Some text</a>
|
||||
|
||||
<div id="scroller">
|
||||
Scrolling on the very left edge of this div will work.
|
||||
Scrolling on the right side of this div (starting with the left edge of the orange box above) should work, but doesn't.<br/>
|
||||
0<br>
|
||||
1<br>
|
||||
2<br>
|
||||
3<br>
|
||||
4<br>
|
||||
5<br>
|
||||
6<br>
|
||||
7<br>
|
||||
8<br>
|
||||
9<br>
|
||||
10<br>
|
||||
11<br>
|
||||
12<br>
|
||||
13<br>
|
||||
14<br>
|
||||
15<br>
|
||||
16<br>
|
||||
17<br>
|
||||
18<br>
|
||||
19<br>
|
||||
20<br>
|
||||
21<br>
|
||||
22<br>
|
||||
23<br>
|
||||
24<br>
|
||||
25<br>
|
||||
26<br>
|
||||
27<br>
|
||||
28<br>
|
||||
29<br>
|
||||
30<br>
|
||||
31<br>
|
||||
32<br>
|
||||
33<br>
|
||||
34<br>
|
||||
35<br>
|
||||
36<br>
|
||||
37<br>
|
||||
38<br>
|
||||
39<br>
|
||||
40<br>
|
||||
41<br>
|
||||
42<br>
|
||||
43<br>
|
||||
44<br>
|
||||
45<br>
|
||||
46<br>
|
||||
47<br>
|
||||
48<br>
|
||||
49<br>
|
||||
50<br>
|
||||
51<br>
|
||||
52<br>
|
||||
53<br>
|
||||
54<br>
|
||||
55<br>
|
||||
56<br>
|
||||
57<br>
|
||||
58<br>
|
||||
59<br>
|
||||
60<br>
|
||||
61<br>
|
||||
62<br>
|
||||
63<br>
|
||||
64<br>
|
||||
65<br>
|
||||
66<br>
|
||||
67<br>
|
||||
68<br>
|
||||
69<br>
|
||||
70<br>
|
||||
71<br>
|
||||
72<br>
|
||||
73<br>
|
||||
74<br>
|
||||
75<br>
|
||||
76<br>
|
||||
77<br>
|
||||
78<br>
|
||||
79<br>
|
||||
80<br>
|
||||
81<br>
|
||||
82<br>
|
||||
83<br>
|
||||
84<br>
|
||||
85<br>
|
||||
86<br>
|
||||
87<br>
|
||||
88<br>
|
||||
89<br>
|
||||
90<br>
|
||||
91<br>
|
||||
92<br>
|
||||
93<br>
|
||||
94<br>
|
||||
95<br>
|
||||
96<br>
|
||||
97<br>
|
||||
98<br>
|
||||
99<br>
|
||||
100<br>
|
||||
101<br>
|
||||
102<br>
|
||||
103<br>
|
||||
104<br>
|
||||
105<br>
|
||||
106<br>
|
||||
107<br>
|
||||
108<br>
|
||||
109<br>
|
||||
110<br>
|
||||
111<br>
|
||||
112<br>
|
||||
113<br>
|
||||
114<br>
|
||||
115<br>
|
||||
116<br>
|
||||
117<br>
|
||||
118<br>
|
||||
119<br>
|
||||
120<br>
|
||||
121<br>
|
||||
122<br>
|
||||
123<br>
|
||||
124<br>
|
||||
125<br>
|
||||
126<br>
|
||||
127<br>
|
||||
128<br>
|
||||
129<br>
|
||||
130<br>
|
||||
131<br>
|
||||
132<br>
|
||||
133<br>
|
||||
134<br>
|
||||
135<br>
|
||||
136<br>
|
||||
137<br>
|
||||
138<br>
|
||||
139<br>
|
||||
140<br>
|
||||
141<br>
|
||||
142<br>
|
||||
143<br>
|
||||
144<br>
|
||||
145<br>
|
||||
146<br>
|
||||
147<br>
|
||||
148<br>
|
||||
149<br>
|
||||
150<br>
|
||||
151<br>
|
||||
152<br>
|
||||
153<br>
|
||||
154<br>
|
||||
155<br>
|
||||
156<br>
|
||||
157<br>
|
||||
158<br>
|
||||
159<br>
|
||||
160<br>
|
||||
161<br>
|
||||
162<br>
|
||||
163<br>
|
||||
164<br>
|
||||
165<br>
|
||||
166<br>
|
||||
167<br>
|
||||
168<br>
|
||||
169<br>
|
||||
170<br>
|
||||
171<br>
|
||||
172<br>
|
||||
173<br>
|
||||
174<br>
|
||||
175<br>
|
||||
176<br>
|
||||
177<br>
|
||||
178<br>
|
||||
179<br>
|
||||
180<br>
|
||||
181<br>
|
||||
182<br>
|
||||
183<br>
|
||||
184<br>
|
||||
185<br>
|
||||
186<br>
|
||||
187<br>
|
||||
188<br>
|
||||
189<br>
|
||||
190<br>
|
||||
191<br>
|
||||
192<br>
|
||||
193<br>
|
||||
194<br>
|
||||
195<br>
|
||||
196<br>
|
||||
197<br>
|
||||
198<br>
|
||||
199<br>
|
||||
200<br>
|
||||
201<br>
|
||||
202<br>
|
||||
203<br>
|
||||
204<br>
|
||||
205<br>
|
||||
206<br>
|
||||
207<br>
|
||||
208<br>
|
||||
209<br>
|
||||
210<br>
|
||||
211<br>
|
||||
212<br>
|
||||
213<br>
|
||||
214<br>
|
||||
215<br>
|
||||
216<br>
|
||||
217<br>
|
||||
218<br>
|
||||
219<br>
|
||||
220<br>
|
||||
221<br>
|
||||
222<br>
|
||||
223<br>
|
||||
224<br>
|
||||
225<br>
|
||||
226<br>
|
||||
227<br>
|
||||
228<br>
|
||||
229<br>
|
||||
230<br>
|
||||
231<br>
|
||||
232<br>
|
||||
233<br>
|
||||
234<br>
|
||||
235<br>
|
||||
236<br>
|
||||
237<br>
|
||||
238<br>
|
||||
239<br>
|
||||
240<br>
|
||||
241<br>
|
||||
242<br>
|
||||
243<br>
|
||||
244<br>
|
||||
245<br>
|
||||
246<br>
|
||||
247<br>
|
||||
248<br>
|
||||
249<br>
|
||||
250<br>
|
||||
251<br>
|
||||
252<br>
|
||||
253<br>
|
||||
254<br>
|
||||
255<br>
|
||||
256<br>
|
||||
257<br>
|
||||
258<br>
|
||||
259<br>
|
||||
260<br>
|
||||
261<br>
|
||||
262<br>
|
||||
263<br>
|
||||
264<br>
|
||||
265<br>
|
||||
266<br>
|
||||
267<br>
|
||||
268<br>
|
||||
269<br>
|
||||
270<br>
|
||||
271<br>
|
||||
272<br>
|
||||
273<br>
|
||||
274<br>
|
||||
275<br>
|
||||
276<br>
|
||||
277<br>
|
||||
278<br>
|
||||
279<br>
|
||||
280<br>
|
||||
281<br>
|
||||
282<br>
|
||||
283<br>
|
||||
284<br>
|
||||
285<br>
|
||||
286<br>
|
||||
287<br>
|
||||
288<br>
|
||||
289<br>
|
||||
290<br>
|
||||
291<br>
|
||||
292<br>
|
||||
293<br>
|
||||
294<br>
|
||||
295<br>
|
||||
296<br>
|
||||
297<br>
|
||||
298<br>
|
||||
299<br>
|
||||
300<br>
|
||||
301<br>
|
||||
302<br>
|
||||
303<br>
|
||||
304<br>
|
||||
305<br>
|
||||
306<br>
|
||||
307<br>
|
||||
308<br>
|
||||
309<br>
|
||||
310<br>
|
||||
311<br>
|
||||
312<br>
|
||||
313<br>
|
||||
314<br>
|
||||
315<br>
|
||||
316<br>
|
||||
317<br>
|
||||
318<br>
|
||||
319<br>
|
||||
320<br>
|
||||
321<br>
|
||||
322<br>
|
||||
323<br>
|
||||
324<br>
|
||||
325<br>
|
||||
326<br>
|
||||
327<br>
|
||||
328<br>
|
||||
329<br>
|
||||
330<br>
|
||||
331<br>
|
||||
332<br>
|
||||
333<br>
|
||||
334<br>
|
||||
335<br>
|
||||
336<br>
|
||||
337<br>
|
||||
338<br>
|
||||
339<br>
|
||||
340<br>
|
||||
341<br>
|
||||
342<br>
|
||||
343<br>
|
||||
344<br>
|
||||
345<br>
|
||||
346<br>
|
||||
347<br>
|
||||
348<br>
|
||||
349<br>
|
||||
350<br>
|
||||
351<br>
|
||||
352<br>
|
||||
353<br>
|
||||
354<br>
|
||||
355<br>
|
||||
356<br>
|
||||
357<br>
|
||||
358<br>
|
||||
359<br>
|
||||
360<br>
|
||||
361<br>
|
||||
362<br>
|
||||
363<br>
|
||||
364<br>
|
||||
365<br>
|
||||
366<br>
|
||||
367<br>
|
||||
368<br>
|
||||
369<br>
|
||||
370<br>
|
||||
371<br>
|
||||
372<br>
|
||||
373<br>
|
||||
374<br>
|
||||
375<br>
|
||||
376<br>
|
||||
377<br>
|
||||
378<br>
|
||||
379<br>
|
||||
380<br>
|
||||
381<br>
|
||||
382<br>
|
||||
383<br>
|
||||
384<br>
|
||||
385<br>
|
||||
386<br>
|
||||
387<br>
|
||||
388<br>
|
||||
389<br>
|
||||
390<br>
|
||||
391<br>
|
||||
392<br>
|
||||
393<br>
|
||||
394<br>
|
||||
395<br>
|
||||
396<br>
|
||||
397<br>
|
||||
398<br>
|
||||
399<br>
|
||||
400<br>
|
||||
401<br>
|
||||
402<br>
|
||||
403<br>
|
||||
404<br>
|
||||
405<br>
|
||||
406<br>
|
||||
407<br>
|
||||
408<br>
|
||||
409<br>
|
||||
410<br>
|
||||
411<br>
|
||||
412<br>
|
||||
413<br>
|
||||
414<br>
|
||||
415<br>
|
||||
416<br>
|
||||
417<br>
|
||||
418<br>
|
||||
419<br>
|
||||
420<br>
|
||||
421<br>
|
||||
422<br>
|
||||
423<br>
|
||||
424<br>
|
||||
425<br>
|
||||
426<br>
|
||||
427<br>
|
||||
428<br>
|
||||
429<br>
|
||||
430<br>
|
||||
431<br>
|
||||
432<br>
|
||||
433<br>
|
||||
434<br>
|
||||
435<br>
|
||||
436<br>
|
||||
437<br>
|
||||
438<br>
|
||||
439<br>
|
||||
440<br>
|
||||
441<br>
|
||||
442<br>
|
||||
443<br>
|
||||
444<br>
|
||||
445<br>
|
||||
446<br>
|
||||
447<br>
|
||||
448<br>
|
||||
449<br>
|
||||
450<br>
|
||||
451<br>
|
||||
452<br>
|
||||
453<br>
|
||||
454<br>
|
||||
455<br>
|
||||
456<br>
|
||||
457<br>
|
||||
458<br>
|
||||
459<br>
|
||||
460<br>
|
||||
461<br>
|
||||
462<br>
|
||||
463<br>
|
||||
464<br>
|
||||
465<br>
|
||||
466<br>
|
||||
467<br>
|
||||
468<br>
|
||||
469<br>
|
||||
470<br>
|
||||
471<br>
|
||||
472<br>
|
||||
473<br>
|
||||
474<br>
|
||||
475<br>
|
||||
476<br>
|
||||
477<br>
|
||||
478<br>
|
||||
479<br>
|
||||
480<br>
|
||||
481<br>
|
||||
482<br>
|
||||
483<br>
|
||||
484<br>
|
||||
485<br>
|
||||
486<br>
|
||||
487<br>
|
||||
488<br>
|
||||
489<br>
|
||||
490<br>
|
||||
491<br>
|
||||
492<br>
|
||||
493<br>
|
||||
494<br>
|
||||
495<br>
|
||||
496<br>
|
||||
497<br>
|
||||
498<br>
|
||||
499<br>
|
||||
</div>
|
||||
<div style="height: 1000px">this div makes the page scrollable</div>
|
||||
</body>
|
||||
74
gfx/layers/apz/test/mochitest/helper_bug1280013.html
Normal file
74
gfx/layers/apz/test/mochitest/helper_bug1280013.html
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html style="overflow:hidden">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<!-- The viewport tag will result in APZ being in a "zoomed-in" state, assuming
|
||||
the device width is less than 980px. -->
|
||||
<meta name="viewport" content="width=980; initial-scale=1.0">
|
||||
<title>Test for bug 1280013</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
function* test(testDriver) {
|
||||
SimpleTest.ok(screen.height > 500, "Screen height must be at least 500 pixels for this test to work");
|
||||
|
||||
// This listener will trigger the test to continue once APZ is done with
|
||||
// processing the scroll.
|
||||
SpecialPowers.Services.obs.addObserver(testDriver, "APZ:TransformEnd", false);
|
||||
|
||||
// Scroll down to the iframe. Do it in two drags instead of one in case the
|
||||
// device screen is short
|
||||
yield synthesizeNativeTouchDrag(document.body, 10, 400, 0, -(350 + TOUCH_SLOP));
|
||||
yield synthesizeNativeTouchDrag(document.body, 10, 400, 0, -(350 + TOUCH_SLOP));
|
||||
// Now the top of the visible area should be at y=700 of the top-level page,
|
||||
// so if the screen is >= 500px tall, the entire iframe should be visible, at
|
||||
// least vertically.
|
||||
|
||||
// However, because of the overflow:hidden on the root elements, all this
|
||||
// scrolling is happening in APZ and is not reflected in the main-thread
|
||||
// scroll position (it is stored in the callback transform instead). We check
|
||||
// this by checking the scroll offset.
|
||||
yield flushApzRepaints(testDriver);
|
||||
SimpleTest.is(window.scrollY, 0, "Main-thread scroll position is still at 0");
|
||||
|
||||
// Scroll the iframe by 300px. Note that since the main-thread scroll position
|
||||
// is still 0, the subframe's getBoundingClientRect is going to be off by
|
||||
// 700 pixels, so we compensate for that here.
|
||||
var subframe = document.getElementById('subframe');
|
||||
yield synthesizeNativeTouchDrag(subframe, 10, 200 - 700, 0, -(300 + TOUCH_SLOP));
|
||||
|
||||
// Remove the observer, we don't need it any more.
|
||||
SpecialPowers.Services.obs.removeObserver(testDriver, "APZ:TransformEnd", false);
|
||||
|
||||
// Flush any pending paints
|
||||
yield flushApzRepaints(testDriver);
|
||||
|
||||
// get the displayport for the subframe
|
||||
var utils = SpecialPowers.getDOMWindowUtils(window);
|
||||
var contentPaints = utils.getContentAPZTestData().paints;
|
||||
var lastPaint = convertScrollFrameData(contentPaints[contentPaints.length - 1].scrollFrames);
|
||||
var foundIt = 0;
|
||||
for (var scrollId in lastPaint) {
|
||||
if (('contentDescription' in lastPaint[scrollId]) &&
|
||||
(lastPaint[scrollId]['contentDescription'].includes('tall_html'))) {
|
||||
var dp = getPropertyAsRect(lastPaint, scrollId, 'criticalDisplayport');
|
||||
SimpleTest.ok(dp.y <= 0, 'The critical displayport top should be less than or equal to zero to cover the visible part of the subframe; it is ' + dp.y);
|
||||
SimpleTest.ok(dp.y + dp.h >= subframe.clientHeight, 'The critical displayport bottom should be greater than the clientHeight; it is ' + (dp.y + dp.h));
|
||||
foundIt++;
|
||||
}
|
||||
}
|
||||
SimpleTest.is(foundIt, 1, "Found exactly one critical displayport for the subframe we were interested in.");
|
||||
}
|
||||
|
||||
waitUntilApzStable()
|
||||
.then(runContinuation(test))
|
||||
.then(subtestDone);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body style="overflow:hidden">
|
||||
The iframe below is at (0, 800). Scroll it into view, and then scroll the contents. The content should be fully rendered in high-resolution.
|
||||
<iframe id="subframe" style="position:absolute; left: 0px; top: 800px; width: 600px; height: 350px" src="helper_tall.html"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
44
gfx/layers/apz/test/mochitest/helper_bug1285070.html
Normal file
44
gfx/layers/apz/test/mochitest/helper_bug1285070.html
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Test pointer events are dispatched once for touch tap</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript">
|
||||
function test() {
|
||||
let pointerEventsList = ["pointerover", "pointerenter", "pointerdown",
|
||||
"pointerup", "pointerleave", "pointerout"];
|
||||
let pointerEventsCount = {};
|
||||
|
||||
pointerEventsList.forEach((eventName) => {
|
||||
pointerEventsCount[eventName] = 0;
|
||||
document.getElementById('div1').addEventListener(eventName, (event) => {
|
||||
dump("Received event " + event.type + "\n");
|
||||
++pointerEventsCount[event.type];
|
||||
}, false);
|
||||
});
|
||||
|
||||
document.addEventListener("click", (event) => {
|
||||
is(event.target, document.getElementById('div1'), "Clicked on div (at " + event.clientX + "," + event.clientY + ")");
|
||||
for (var key in pointerEventsCount) {
|
||||
is(pointerEventsCount[key], 1, "Event " + key + " should be generated once");
|
||||
}
|
||||
subtestDone();
|
||||
}, false);
|
||||
|
||||
synthesizeNativeTap(document.getElementById('div1'), 100, 100, () => {
|
||||
dump("Finished synthesizing tap, waiting for div to be clicked...\n");
|
||||
});
|
||||
}
|
||||
|
||||
waitUntilApzStable().then(test);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="div1" style="width: 200px; height: 200px; background: black"></div>
|
||||
</body>
|
||||
</html>
|
||||
47
gfx/layers/apz/test/mochitest/helper_bug1299195.html
Normal file
47
gfx/layers/apz/test/mochitest/helper_bug1299195.html
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Test pointer events are dispatched once for touch tap</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript">
|
||||
/** Test for Bug 1299195 **/
|
||||
function runTests() {
|
||||
let target0 = document.getElementById("target0");
|
||||
let mouseup_count = 0;
|
||||
let mousedown_count = 0;
|
||||
let pointerup_count = 0;
|
||||
let pointerdown_count = 0;
|
||||
|
||||
target0.addEventListener("mouseup", () => {
|
||||
++mouseup_count;
|
||||
if (mouseup_count == 2) {
|
||||
is(mousedown_count, 2, "Double tap with touch should fire 2 mousedown events");
|
||||
is(mouseup_count, 2, "Double tap with touch should fire 2 mouseup events");
|
||||
is(pointerdown_count, 2, "Double tap with touch should fire 2 pointerdown events");
|
||||
is(pointerup_count, 2, "Double tap with touch should fire 2 pointerup events");
|
||||
subtestDone();
|
||||
}
|
||||
});
|
||||
target0.addEventListener("mousedown", () => {
|
||||
++mousedown_count;
|
||||
});
|
||||
target0.addEventListener("pointerup", () => {
|
||||
++pointerup_count;
|
||||
});
|
||||
target0.addEventListener("pointerdown", () => {
|
||||
++pointerdown_count;
|
||||
});
|
||||
synthesizeNativeTap(document.getElementById('target0'), 100, 100);
|
||||
synthesizeNativeTap(document.getElementById('target0'), 100, 100);
|
||||
}
|
||||
waitUntilApzStable().then(runTests);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="target0" style="width: 200px; height: 200px; background: green"></div>
|
||||
</body>
|
||||
</html>
|
||||
149
gfx/layers/apz/test/mochitest/helper_bug982141.html
Normal file
149
gfx/layers/apz/test/mochitest/helper_bug982141.html
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=982141
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="user-scalable=no">
|
||||
<title>Test for Bug 982141, helper page</title>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Infrastructure to get the test assertions to run at the right time.
|
||||
// -------------------------------------------------------------------
|
||||
var SimpleTest = window.opener.SimpleTest;
|
||||
|
||||
window.onload = function() {
|
||||
window.addEventListener("MozAfterPaint", afterPaint, false);
|
||||
};
|
||||
var utils = SpecialPowers.getDOMWindowUtils(window);
|
||||
function afterPaint(e) {
|
||||
// If there is another paint pending, wait for it.
|
||||
if (utils.isMozAfterPaintPending) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Once there are no more paints pending, remove the
|
||||
// MozAfterPaint listener and run the test logic.
|
||||
window.removeEventListener("MozAfterPaint", afterPaint, false);
|
||||
testBug982141();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// The actual logic for testing bug 982141.
|
||||
//
|
||||
// In this test we have a simple page with a scrollable <div> which has
|
||||
// enough content to make it scrollable. We test that this <div> got
|
||||
// a displayport.
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
function testBug982141() {
|
||||
// Get the content- and compositor-side test data from nsIDOMWindowUtils.
|
||||
var contentTestData = utils.getContentAPZTestData();
|
||||
var compositorTestData = utils.getCompositorAPZTestData();
|
||||
|
||||
// Get the sequence number of the last paint on the compositor side.
|
||||
// We do this before converting the APZ test data because the conversion
|
||||
// loses the order of the paints.
|
||||
SimpleTest.ok(compositorTestData.paints.length > 0,
|
||||
"expected at least one paint in compositor test data");
|
||||
var lastCompositorPaint = compositorTestData.paints[compositorTestData.paints.length - 1];
|
||||
var lastCompositorPaintSeqNo = lastCompositorPaint.sequenceNumber;
|
||||
|
||||
// Convert the test data into a representation that's easier to navigate.
|
||||
contentTestData = convertTestData(contentTestData);
|
||||
compositorTestData = convertTestData(compositorTestData);
|
||||
|
||||
// Reconstruct the APZC tree structure in the last paint.
|
||||
var apzcTree = buildApzcTree(compositorTestData.paints[lastCompositorPaintSeqNo]);
|
||||
|
||||
// The apzc tree for this page should consist of a single child APZC on
|
||||
// the RCD node (the child is for scrollable <div>). Note that in e10s/B2G
|
||||
// cases the RCD will be the root of the tree but on Fennec it will not.
|
||||
var rcd = findRcdNode(apzcTree);
|
||||
SimpleTest.ok(rcd != null, "found the RCD node");
|
||||
SimpleTest.is(rcd.children.length, 1, "expected a single child APZC");
|
||||
var childScrollId = rcd.children[0].scrollId;
|
||||
|
||||
// We should have content-side data for the same paint.
|
||||
SimpleTest.ok(lastCompositorPaintSeqNo in contentTestData.paints,
|
||||
"expected a content paint with sequence number" + lastCompositorPaintSeqNo);
|
||||
var correspondingContentPaint = contentTestData.paints[lastCompositorPaintSeqNo];
|
||||
|
||||
var dp = getPropertyAsRect(correspondingContentPaint, childScrollId, 'displayport');
|
||||
var subframe = document.getElementById('subframe');
|
||||
// The clientWidth and clientHeight may be less than 50 if there are scrollbars showing.
|
||||
// In general they will be (50 - <scrollbarwidth>, 50 - <scrollbarheight>).
|
||||
SimpleTest.ok(subframe.clientWidth > 0, "Expected a non-zero clientWidth, got: " + subframe.clientWidth);
|
||||
SimpleTest.ok(subframe.clientHeight > 0, "Expected a non-zero clientHeight, got: " + subframe.clientHeight);
|
||||
SimpleTest.ok(dp.w >= subframe.clientWidth && dp.h >= subframe.clientHeight,
|
||||
"expected a displayport at least as large as the scrollable element, got " + JSON.stringify(dp));
|
||||
|
||||
window.opener.finishTest();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body style="overflow: hidden;"><!-- This combined with the user-scalable=no ensures the root frame is not scrollable -->
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=982141">Mozilla Bug 982141</a>
|
||||
<!-- A scrollable subframe, with enough content to make it have a nonzero scroll range -->
|
||||
<div id="subframe" style="height: 50px; width: 50px; overflow: scroll">
|
||||
<div style="width: 100px">
|
||||
Wide content so that the vertical scrollbar for the parent div
|
||||
doesn't eat into the 50px width and reduce the width of the
|
||||
displayport.
|
||||
</div>
|
||||
Line 1<br>
|
||||
Line 2<br>
|
||||
Line 3<br>
|
||||
Line 4<br>
|
||||
Line 5<br>
|
||||
Line 6<br>
|
||||
Line 7<br>
|
||||
Line 8<br>
|
||||
Line 9<br>
|
||||
Line 10<br>
|
||||
Line 11<br>
|
||||
Line 12<br>
|
||||
Line 13<br>
|
||||
Line 14<br>
|
||||
Line 15<br>
|
||||
Line 16<br>
|
||||
Line 17<br>
|
||||
Line 18<br>
|
||||
Line 19<br>
|
||||
Line 20<br>
|
||||
Line 21<br>
|
||||
Line 22<br>
|
||||
Line 23<br>
|
||||
Line 24<br>
|
||||
Line 25<br>
|
||||
Line 26<br>
|
||||
Line 27<br>
|
||||
Line 28<br>
|
||||
Line 29<br>
|
||||
Line 30<br>
|
||||
Line 31<br>
|
||||
Line 32<br>
|
||||
Line 33<br>
|
||||
Line 34<br>
|
||||
Line 35<br>
|
||||
Line 36<br>
|
||||
Line 37<br>
|
||||
Line 38<br>
|
||||
Line 39<br>
|
||||
Line 40<br>
|
||||
Line 41<br>
|
||||
Line 42<br>
|
||||
Line 43<br>
|
||||
Line 44<br>
|
||||
Line 45<br>
|
||||
Line 46<br>
|
||||
Line 40<br>
|
||||
Line 48<br>
|
||||
Line 49<br>
|
||||
Line 50<br>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
41
gfx/layers/apz/test/mochitest/helper_click.html
Normal file
41
gfx/layers/apz/test/mochitest/helper_click.html
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Sanity mouse-clicking test</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function* clickButton(testDriver) {
|
||||
document.addEventListener('click', clicked, false);
|
||||
|
||||
if (getQueryArgs()['dtc']) {
|
||||
// force a dispatch-to-content region on the document
|
||||
document.addEventListener('wheel', function() { /* no-op */ }, { passive: false });
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
}
|
||||
|
||||
synthesizeNativeClick(document.getElementById('b'), 5, 5, function() {
|
||||
dump("Finished synthesizing click, waiting for button to be clicked...\n");
|
||||
});
|
||||
}
|
||||
|
||||
function clicked(e) {
|
||||
is(e.target, document.getElementById('b'), "Clicked on button, yay! (at " + e.clientX + "," + e.clientY + ")");
|
||||
subtestDone();
|
||||
}
|
||||
|
||||
waitUntilApzStable()
|
||||
.then(runContinuation(clickButton));
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<button id="b" style="width: 10px; height: 10px"></button>
|
||||
</body>
|
||||
</html>
|
||||
44
gfx/layers/apz/test/mochitest/helper_div_pan.html
Normal file
44
gfx/layers/apz/test/mochitest/helper_div_pan.html
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Sanity panning test for scrollable div</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function scrollOuter() {
|
||||
var transformEnd = function() {
|
||||
SpecialPowers.Services.obs.removeObserver(transformEnd, "APZ:TransformEnd", false);
|
||||
dump("Transform complete; flushing repaints...\n");
|
||||
flushApzRepaints(checkScroll);
|
||||
};
|
||||
SpecialPowers.Services.obs.addObserver(transformEnd, "APZ:TransformEnd", false);
|
||||
|
||||
synthesizeNativeTouchDrag(document.getElementById('outer'), 10, 100, 0, -(50 + TOUCH_SLOP));
|
||||
dump("Finished native drag, waiting for transform-end observer...\n");
|
||||
}
|
||||
|
||||
function checkScroll() {
|
||||
var outerScroll = document.getElementById('outer').scrollTop;
|
||||
is(outerScroll, 50, "check that the div scrolled");
|
||||
subtestDone();
|
||||
}
|
||||
|
||||
waitUntilApzStable().then(scrollOuter);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="outer" style="height: 250px; border: solid 1px black; overflow:scroll">
|
||||
<div style="height: 5000px; background-color: lightblue">
|
||||
This div makes the |outer| div scrollable.
|
||||
</div>
|
||||
</div>
|
||||
<div style="height: 5000px; background-color: lightgreen;">
|
||||
This div makes the top-level page scrollable.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
43
gfx/layers/apz/test/mochitest/helper_drag_click.html
Normal file
43
gfx/layers/apz/test/mochitest/helper_drag_click.html
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Sanity mouse-drag click test</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function* test(testDriver) {
|
||||
document.addEventListener('click', clicked, false);
|
||||
|
||||
// Ensure the pointer is inside the window
|
||||
yield synthesizeNativeMouseEvent(document.getElementById('b'), 5, 5, nativeMouseMoveEventMsg(), testDriver);
|
||||
// mouse down, move it around, and release it near where it went down. this
|
||||
// should generate a click at the release point
|
||||
yield synthesizeNativeMouseEvent(document.getElementById('b'), 5, 5, nativeMouseDownEventMsg(), testDriver);
|
||||
yield synthesizeNativeMouseEvent(document.getElementById('b'), 100, 100, nativeMouseMoveEventMsg(), testDriver);
|
||||
yield synthesizeNativeMouseEvent(document.getElementById('b'), 10, 10, nativeMouseMoveEventMsg(), testDriver);
|
||||
yield synthesizeNativeMouseEvent(document.getElementById('b'), 8, 8, nativeMouseUpEventMsg(), testDriver);
|
||||
dump("Finished synthesizing click with a drag in the middle\n");
|
||||
}
|
||||
|
||||
function clicked(e) {
|
||||
// The mouse down at (5, 5) should not have generated a click, but the up
|
||||
// at (8, 8) should have.
|
||||
is(e.target, document.getElementById('b'), "Clicked on button, yay! (at " + e.clientX + "," + e.clientY + ")");
|
||||
is(e.clientX, 8 + Math.floor(document.getElementById('b').getBoundingClientRect().left), 'x-coord of click event looks sane');
|
||||
is(e.clientY, 8 + Math.floor(document.getElementById('b').getBoundingClientRect().top), 'y-coord of click event looks sane');
|
||||
subtestDone();
|
||||
}
|
||||
|
||||
waitUntilApzStable()
|
||||
.then(runContinuation(test));
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<button id="b" style="width: 10px; height: 10px"></button>
|
||||
</body>
|
||||
</html>
|
||||
603
gfx/layers/apz/test/mochitest/helper_drag_scroll.html
Normal file
603
gfx/layers/apz/test/mochitest/helper_drag_scroll.html
Normal file
|
|
@ -0,0 +1,603 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Dragging the mouse on a content-implemented scrollbar</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<style>
|
||||
body {
|
||||
background: linear-gradient(135deg, red, blue);
|
||||
}
|
||||
#scrollbar {
|
||||
position:fixed;
|
||||
top: 0;
|
||||
right: 10px;
|
||||
height: 100%;
|
||||
width: 150px;
|
||||
background-color: gray;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
var bar = null;
|
||||
var mouseDown = false;
|
||||
|
||||
function moveTo(mouseY, testDriver) {
|
||||
var fraction = (mouseY - bar.getBoundingClientRect().top) / bar.getBoundingClientRect().height;
|
||||
fraction = Math.max(0, fraction);
|
||||
fraction = Math.min(1, fraction);
|
||||
var oldScrollPos = document.scrollingElement.scrollTop;
|
||||
var newScrollPos = fraction * window.scrollMaxY;
|
||||
SimpleTest.ok(newScrollPos > oldScrollPos, "Scroll position strictly increased");
|
||||
// split the scroll in two with a paint in between, just to increase the
|
||||
// complexity of the simulated web content, and to ensure this works as well.
|
||||
document.scrollingElement.scrollTop = (oldScrollPos + newScrollPos) / 2;
|
||||
waitForAllPaints(function() {
|
||||
document.scrollingElement.scrollTop = newScrollPos;
|
||||
testDriver();
|
||||
});
|
||||
}
|
||||
|
||||
function setupDragging(testDriver) {
|
||||
bar = document.getElementById('scrollbar');
|
||||
mouseDown = false;
|
||||
|
||||
bar.addEventListener('mousedown', function(e) {
|
||||
mouseDown = true;
|
||||
moveTo(e.clientY, testDriver);
|
||||
}, true);
|
||||
|
||||
bar.addEventListener('mousemove', function(e) {
|
||||
if (mouseDown) {
|
||||
dump("Got mousemove clientY " + e.clientY + "\n");
|
||||
moveTo(e.clientY, testDriver);
|
||||
e.stopPropagation();
|
||||
}
|
||||
}, true);
|
||||
|
||||
bar.addEventListener('mouseup', function(e) {
|
||||
mouseDown = false;
|
||||
}, true);
|
||||
|
||||
window.addEventListener('mousemove', function(e) {
|
||||
if (mouseDown) {
|
||||
SimpleTest.ok(false, "The mousemove at " + e.clientY + " was not stopped by the bar listener, and is a glitchy event!");
|
||||
setTimeout(testDriver, 0);
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
function* test(testDriver) {
|
||||
setupDragging(testDriver);
|
||||
|
||||
// Move the mouse to the "scrollbar" (the div upon which dragging changes scroll position)
|
||||
yield synthesizeNativeMouseEvent(bar, 10, 10, nativeMouseMoveEventMsg(), testDriver);
|
||||
// mouse down
|
||||
yield synthesizeNativeMouseEvent(bar, 10, 10, nativeMouseDownEventMsg());
|
||||
// drag vertically by 400px, in 50px increments
|
||||
yield synthesizeNativeMouseEvent(bar, 10, 60, nativeMouseMoveEventMsg());
|
||||
yield synthesizeNativeMouseEvent(bar, 10, 110, nativeMouseMoveEventMsg());
|
||||
yield synthesizeNativeMouseEvent(bar, 10, 160, nativeMouseMoveEventMsg());
|
||||
yield synthesizeNativeMouseEvent(bar, 10, 210, nativeMouseMoveEventMsg());
|
||||
yield synthesizeNativeMouseEvent(bar, 10, 260, nativeMouseMoveEventMsg());
|
||||
yield synthesizeNativeMouseEvent(bar, 10, 310, nativeMouseMoveEventMsg());
|
||||
yield synthesizeNativeMouseEvent(bar, 10, 360, nativeMouseMoveEventMsg());
|
||||
yield synthesizeNativeMouseEvent(bar, 10, 410, nativeMouseMoveEventMsg());
|
||||
// and release
|
||||
yield synthesizeNativeMouseEvent(bar, 10, 410, nativeMouseUpEventMsg(), testDriver);
|
||||
}
|
||||
|
||||
waitUntilApzStable()
|
||||
.then(runContinuation(test))
|
||||
.then(subtestDone);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="scrollbar">Drag up and down on this bar. The background/scrollbar shouldn't glitch</div>
|
||||
This is a tall page<br/>
|
||||
1<br/>
|
||||
2<br/>
|
||||
3<br/>
|
||||
4<br/>
|
||||
5<br/>
|
||||
6<br/>
|
||||
7<br/>
|
||||
8<br/>
|
||||
9<br/>
|
||||
10<br/>
|
||||
11<br/>
|
||||
12<br/>
|
||||
13<br/>
|
||||
14<br/>
|
||||
15<br/>
|
||||
16<br/>
|
||||
17<br/>
|
||||
18<br/>
|
||||
19<br/>
|
||||
20<br/>
|
||||
21<br/>
|
||||
22<br/>
|
||||
23<br/>
|
||||
24<br/>
|
||||
25<br/>
|
||||
26<br/>
|
||||
27<br/>
|
||||
28<br/>
|
||||
29<br/>
|
||||
30<br/>
|
||||
31<br/>
|
||||
32<br/>
|
||||
33<br/>
|
||||
34<br/>
|
||||
35<br/>
|
||||
36<br/>
|
||||
37<br/>
|
||||
38<br/>
|
||||
39<br/>
|
||||
40<br/>
|
||||
41<br/>
|
||||
42<br/>
|
||||
43<br/>
|
||||
44<br/>
|
||||
45<br/>
|
||||
46<br/>
|
||||
47<br/>
|
||||
48<br/>
|
||||
49<br/>
|
||||
50<br/>
|
||||
51<br/>
|
||||
52<br/>
|
||||
53<br/>
|
||||
54<br/>
|
||||
55<br/>
|
||||
56<br/>
|
||||
57<br/>
|
||||
58<br/>
|
||||
59<br/>
|
||||
60<br/>
|
||||
61<br/>
|
||||
62<br/>
|
||||
63<br/>
|
||||
64<br/>
|
||||
65<br/>
|
||||
66<br/>
|
||||
67<br/>
|
||||
68<br/>
|
||||
69<br/>
|
||||
70<br/>
|
||||
71<br/>
|
||||
72<br/>
|
||||
73<br/>
|
||||
74<br/>
|
||||
75<br/>
|
||||
76<br/>
|
||||
77<br/>
|
||||
78<br/>
|
||||
79<br/>
|
||||
80<br/>
|
||||
81<br/>
|
||||
82<br/>
|
||||
83<br/>
|
||||
84<br/>
|
||||
85<br/>
|
||||
86<br/>
|
||||
87<br/>
|
||||
88<br/>
|
||||
89<br/>
|
||||
90<br/>
|
||||
91<br/>
|
||||
92<br/>
|
||||
93<br/>
|
||||
94<br/>
|
||||
95<br/>
|
||||
96<br/>
|
||||
97<br/>
|
||||
98<br/>
|
||||
99<br/>
|
||||
100<br/>
|
||||
101<br/>
|
||||
102<br/>
|
||||
103<br/>
|
||||
104<br/>
|
||||
105<br/>
|
||||
106<br/>
|
||||
107<br/>
|
||||
108<br/>
|
||||
109<br/>
|
||||
110<br/>
|
||||
111<br/>
|
||||
112<br/>
|
||||
113<br/>
|
||||
114<br/>
|
||||
115<br/>
|
||||
116<br/>
|
||||
117<br/>
|
||||
118<br/>
|
||||
119<br/>
|
||||
120<br/>
|
||||
121<br/>
|
||||
122<br/>
|
||||
123<br/>
|
||||
124<br/>
|
||||
125<br/>
|
||||
126<br/>
|
||||
127<br/>
|
||||
128<br/>
|
||||
129<br/>
|
||||
130<br/>
|
||||
131<br/>
|
||||
132<br/>
|
||||
133<br/>
|
||||
134<br/>
|
||||
135<br/>
|
||||
136<br/>
|
||||
137<br/>
|
||||
138<br/>
|
||||
139<br/>
|
||||
140<br/>
|
||||
141<br/>
|
||||
142<br/>
|
||||
143<br/>
|
||||
144<br/>
|
||||
145<br/>
|
||||
146<br/>
|
||||
147<br/>
|
||||
148<br/>
|
||||
149<br/>
|
||||
150<br/>
|
||||
151<br/>
|
||||
152<br/>
|
||||
153<br/>
|
||||
154<br/>
|
||||
155<br/>
|
||||
156<br/>
|
||||
157<br/>
|
||||
158<br/>
|
||||
159<br/>
|
||||
160<br/>
|
||||
161<br/>
|
||||
162<br/>
|
||||
163<br/>
|
||||
164<br/>
|
||||
165<br/>
|
||||
166<br/>
|
||||
167<br/>
|
||||
168<br/>
|
||||
169<br/>
|
||||
170<br/>
|
||||
171<br/>
|
||||
172<br/>
|
||||
173<br/>
|
||||
174<br/>
|
||||
175<br/>
|
||||
176<br/>
|
||||
177<br/>
|
||||
178<br/>
|
||||
179<br/>
|
||||
180<br/>
|
||||
181<br/>
|
||||
182<br/>
|
||||
183<br/>
|
||||
184<br/>
|
||||
185<br/>
|
||||
186<br/>
|
||||
187<br/>
|
||||
188<br/>
|
||||
189<br/>
|
||||
190<br/>
|
||||
191<br/>
|
||||
192<br/>
|
||||
193<br/>
|
||||
194<br/>
|
||||
195<br/>
|
||||
196<br/>
|
||||
197<br/>
|
||||
198<br/>
|
||||
199<br/>
|
||||
200<br/>
|
||||
201<br/>
|
||||
202<br/>
|
||||
203<br/>
|
||||
204<br/>
|
||||
205<br/>
|
||||
206<br/>
|
||||
207<br/>
|
||||
208<br/>
|
||||
209<br/>
|
||||
210<br/>
|
||||
211<br/>
|
||||
212<br/>
|
||||
213<br/>
|
||||
214<br/>
|
||||
215<br/>
|
||||
216<br/>
|
||||
217<br/>
|
||||
218<br/>
|
||||
219<br/>
|
||||
220<br/>
|
||||
221<br/>
|
||||
222<br/>
|
||||
223<br/>
|
||||
224<br/>
|
||||
225<br/>
|
||||
226<br/>
|
||||
227<br/>
|
||||
228<br/>
|
||||
229<br/>
|
||||
230<br/>
|
||||
231<br/>
|
||||
232<br/>
|
||||
233<br/>
|
||||
234<br/>
|
||||
235<br/>
|
||||
236<br/>
|
||||
237<br/>
|
||||
238<br/>
|
||||
239<br/>
|
||||
240<br/>
|
||||
241<br/>
|
||||
242<br/>
|
||||
243<br/>
|
||||
244<br/>
|
||||
245<br/>
|
||||
246<br/>
|
||||
247<br/>
|
||||
248<br/>
|
||||
249<br/>
|
||||
250<br/>
|
||||
251<br/>
|
||||
252<br/>
|
||||
253<br/>
|
||||
254<br/>
|
||||
255<br/>
|
||||
256<br/>
|
||||
257<br/>
|
||||
258<br/>
|
||||
259<br/>
|
||||
260<br/>
|
||||
261<br/>
|
||||
262<br/>
|
||||
263<br/>
|
||||
264<br/>
|
||||
265<br/>
|
||||
266<br/>
|
||||
267<br/>
|
||||
268<br/>
|
||||
269<br/>
|
||||
270<br/>
|
||||
271<br/>
|
||||
272<br/>
|
||||
273<br/>
|
||||
274<br/>
|
||||
275<br/>
|
||||
276<br/>
|
||||
277<br/>
|
||||
278<br/>
|
||||
279<br/>
|
||||
280<br/>
|
||||
281<br/>
|
||||
282<br/>
|
||||
283<br/>
|
||||
284<br/>
|
||||
285<br/>
|
||||
286<br/>
|
||||
287<br/>
|
||||
288<br/>
|
||||
289<br/>
|
||||
290<br/>
|
||||
291<br/>
|
||||
292<br/>
|
||||
293<br/>
|
||||
294<br/>
|
||||
295<br/>
|
||||
296<br/>
|
||||
297<br/>
|
||||
298<br/>
|
||||
299<br/>
|
||||
300<br/>
|
||||
301<br/>
|
||||
302<br/>
|
||||
303<br/>
|
||||
304<br/>
|
||||
305<br/>
|
||||
306<br/>
|
||||
307<br/>
|
||||
308<br/>
|
||||
309<br/>
|
||||
310<br/>
|
||||
311<br/>
|
||||
312<br/>
|
||||
313<br/>
|
||||
314<br/>
|
||||
315<br/>
|
||||
316<br/>
|
||||
317<br/>
|
||||
318<br/>
|
||||
319<br/>
|
||||
320<br/>
|
||||
321<br/>
|
||||
322<br/>
|
||||
323<br/>
|
||||
324<br/>
|
||||
325<br/>
|
||||
326<br/>
|
||||
327<br/>
|
||||
328<br/>
|
||||
329<br/>
|
||||
330<br/>
|
||||
331<br/>
|
||||
332<br/>
|
||||
333<br/>
|
||||
334<br/>
|
||||
335<br/>
|
||||
336<br/>
|
||||
337<br/>
|
||||
338<br/>
|
||||
339<br/>
|
||||
340<br/>
|
||||
341<br/>
|
||||
342<br/>
|
||||
343<br/>
|
||||
344<br/>
|
||||
345<br/>
|
||||
346<br/>
|
||||
347<br/>
|
||||
348<br/>
|
||||
349<br/>
|
||||
350<br/>
|
||||
351<br/>
|
||||
352<br/>
|
||||
353<br/>
|
||||
354<br/>
|
||||
355<br/>
|
||||
356<br/>
|
||||
357<br/>
|
||||
358<br/>
|
||||
359<br/>
|
||||
360<br/>
|
||||
361<br/>
|
||||
362<br/>
|
||||
363<br/>
|
||||
364<br/>
|
||||
365<br/>
|
||||
366<br/>
|
||||
367<br/>
|
||||
368<br/>
|
||||
369<br/>
|
||||
370<br/>
|
||||
371<br/>
|
||||
372<br/>
|
||||
373<br/>
|
||||
374<br/>
|
||||
375<br/>
|
||||
376<br/>
|
||||
377<br/>
|
||||
378<br/>
|
||||
379<br/>
|
||||
380<br/>
|
||||
381<br/>
|
||||
382<br/>
|
||||
383<br/>
|
||||
384<br/>
|
||||
385<br/>
|
||||
386<br/>
|
||||
387<br/>
|
||||
388<br/>
|
||||
389<br/>
|
||||
390<br/>
|
||||
391<br/>
|
||||
392<br/>
|
||||
393<br/>
|
||||
394<br/>
|
||||
395<br/>
|
||||
396<br/>
|
||||
397<br/>
|
||||
398<br/>
|
||||
399<br/>
|
||||
400<br/>
|
||||
401<br/>
|
||||
402<br/>
|
||||
403<br/>
|
||||
404<br/>
|
||||
405<br/>
|
||||
406<br/>
|
||||
407<br/>
|
||||
408<br/>
|
||||
409<br/>
|
||||
410<br/>
|
||||
411<br/>
|
||||
412<br/>
|
||||
413<br/>
|
||||
414<br/>
|
||||
415<br/>
|
||||
416<br/>
|
||||
417<br/>
|
||||
418<br/>
|
||||
419<br/>
|
||||
420<br/>
|
||||
421<br/>
|
||||
422<br/>
|
||||
423<br/>
|
||||
424<br/>
|
||||
425<br/>
|
||||
426<br/>
|
||||
427<br/>
|
||||
428<br/>
|
||||
429<br/>
|
||||
430<br/>
|
||||
431<br/>
|
||||
432<br/>
|
||||
433<br/>
|
||||
434<br/>
|
||||
435<br/>
|
||||
436<br/>
|
||||
437<br/>
|
||||
438<br/>
|
||||
439<br/>
|
||||
440<br/>
|
||||
441<br/>
|
||||
442<br/>
|
||||
443<br/>
|
||||
444<br/>
|
||||
445<br/>
|
||||
446<br/>
|
||||
447<br/>
|
||||
448<br/>
|
||||
449<br/>
|
||||
450<br/>
|
||||
451<br/>
|
||||
452<br/>
|
||||
453<br/>
|
||||
454<br/>
|
||||
455<br/>
|
||||
456<br/>
|
||||
457<br/>
|
||||
458<br/>
|
||||
459<br/>
|
||||
460<br/>
|
||||
461<br/>
|
||||
462<br/>
|
||||
463<br/>
|
||||
464<br/>
|
||||
465<br/>
|
||||
466<br/>
|
||||
467<br/>
|
||||
468<br/>
|
||||
469<br/>
|
||||
470<br/>
|
||||
471<br/>
|
||||
472<br/>
|
||||
473<br/>
|
||||
474<br/>
|
||||
475<br/>
|
||||
476<br/>
|
||||
477<br/>
|
||||
478<br/>
|
||||
479<br/>
|
||||
480<br/>
|
||||
481<br/>
|
||||
482<br/>
|
||||
483<br/>
|
||||
484<br/>
|
||||
485<br/>
|
||||
486<br/>
|
||||
487<br/>
|
||||
488<br/>
|
||||
489<br/>
|
||||
490<br/>
|
||||
491<br/>
|
||||
492<br/>
|
||||
493<br/>
|
||||
494<br/>
|
||||
495<br/>
|
||||
496<br/>
|
||||
497<br/>
|
||||
498<br/>
|
||||
499<br/>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
14
gfx/layers/apz/test/mochitest/helper_iframe1.html
Normal file
14
gfx/layers/apz/test/mochitest/helper_iframe1.html
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<!-- The purpose of the 'id' on the HTML element is to get something
|
||||
identifiable to show up in the root scroll frame's content description,
|
||||
so we can check it for layerization. -->
|
||||
<html id="outer3">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="helper_subframe_style.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="inner3" class="inner-frame">
|
||||
<div class="inner-content"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
14
gfx/layers/apz/test/mochitest/helper_iframe2.html
Normal file
14
gfx/layers/apz/test/mochitest/helper_iframe2.html
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE HTML>
|
||||
<!-- The purpose of the 'id' on the HTML element is to get something
|
||||
identifiable to show up in the root scroll frame's content description,
|
||||
so we can check it for layerization. -->
|
||||
<html id="outer4">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="helper_subframe_style.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="inner4" class="inner-frame">
|
||||
<div class="inner-content"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
41
gfx/layers/apz/test/mochitest/helper_iframe_pan.html
Normal file
41
gfx/layers/apz/test/mochitest/helper_iframe_pan.html
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Sanity panning test for scrollable div</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function scrollOuter() {
|
||||
var outer = document.getElementById('outer');
|
||||
var transformEnd = function() {
|
||||
SpecialPowers.Services.obs.removeObserver(transformEnd, "APZ:TransformEnd", false);
|
||||
dump("Transform complete; flushing repaints...\n");
|
||||
flushApzRepaints(checkScroll, outer.contentWindow);
|
||||
};
|
||||
SpecialPowers.Services.obs.addObserver(transformEnd, "APZ:TransformEnd", false);
|
||||
|
||||
synthesizeNativeTouchDrag(outer.contentDocument.body, 10, 100, 0, -(50 + TOUCH_SLOP));
|
||||
dump("Finished native drag, waiting for transform-end observer...\n");
|
||||
}
|
||||
|
||||
function checkScroll() {
|
||||
var outerScroll = document.getElementById('outer').contentWindow.scrollY;
|
||||
is(outerScroll, 50, "check that the iframe scrolled");
|
||||
subtestDone();
|
||||
}
|
||||
|
||||
waitUntilApzStable().then(scrollOuter);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<iframe id="outer" style="height: 250px; border: solid 1px black" src="data:text/html,<body style='height:5000px'>"></iframe>
|
||||
<div style="height: 5000px; background-color: lightgreen;">
|
||||
This div makes the top-level page scrollable.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
81
gfx/layers/apz/test/mochitest/helper_long_tap.html
Normal file
81
gfx/layers/apz/test/mochitest/helper_long_tap.html
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Ensure we get a touch-cancel after a contextmenu comes up</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function longPressLink() {
|
||||
synthesizeNativeTouch(document.getElementById('b'), 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, function() {
|
||||
dump("Finished synthesizing touch-start, waiting for events...\n");
|
||||
});
|
||||
}
|
||||
|
||||
var eventsFired = 0;
|
||||
function recordEvent(e) {
|
||||
if (getPlatform() == "windows") {
|
||||
// On Windows we get a mouselongtap event once the long-tap has been detected
|
||||
// by APZ, and that's what we use as the trigger to lift the finger. That then
|
||||
// triggers the contextmenu. This matches the platform convention.
|
||||
switch (eventsFired) {
|
||||
case 0: is(e.type, 'touchstart', 'Got a touchstart'); break;
|
||||
case 1:
|
||||
is(e.type, 'mouselongtap', 'Got a mouselongtap');
|
||||
synthesizeNativeTouch(document.getElementById('b'), 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE);
|
||||
break;
|
||||
case 2: is(e.type, 'touchend', 'Got a touchend'); break;
|
||||
case 3: is(e.type, 'contextmenu', 'Got a contextmenu'); e.preventDefault(); break;
|
||||
default: ok(false, 'Got an unexpected event of type ' + e.type); break;
|
||||
}
|
||||
eventsFired++;
|
||||
|
||||
if (eventsFired == 4) {
|
||||
dump("Finished waiting for events, doing an APZ flush to see if any more unexpected events come through...\n");
|
||||
flushApzRepaints(function() {
|
||||
dump("Done APZ flush, ending test...\n");
|
||||
subtestDone();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// On non-Windows platforms we get a contextmenu event once the long-tap has
|
||||
// been detected. Since we prevent-default that, we don't get a mouselongtap
|
||||
// event at all, and instead get a touchcancel.
|
||||
switch (eventsFired) {
|
||||
case 0: is(e.type, 'touchstart', 'Got a touchstart'); break;
|
||||
case 1: is(e.type, 'contextmenu', 'Got a contextmenu'); e.preventDefault(); break;
|
||||
case 2: is(e.type, 'touchcancel', 'Got a touchcancel'); break;
|
||||
default: ok(false, 'Got an unexpected event of type ' + e.type); break;
|
||||
}
|
||||
eventsFired++;
|
||||
|
||||
if (eventsFired == 3) {
|
||||
synthesizeNativeTouch(document.getElementById('b'), 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, function() {
|
||||
dump("Finished synthesizing touch-end, doing an APZ flush to see if any more unexpected events come through...\n");
|
||||
flushApzRepaints(function() {
|
||||
dump("Done APZ flush, ending test...\n");
|
||||
subtestDone();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('touchstart', recordEvent, { passive: true, capture: true });
|
||||
window.addEventListener('touchend', recordEvent, { passive: true, capture: true });
|
||||
window.addEventListener('touchcancel', recordEvent, true);
|
||||
window.addEventListener('contextmenu', recordEvent, true);
|
||||
SpecialPowers.addChromeEventListener('mouselongtap', recordEvent, true);
|
||||
|
||||
waitUntilApzStable()
|
||||
.then(longPressLink);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a id="b" href="#">Link to nowhere</a>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<head>
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Wheel-scrolling over inactive subframe with perspective</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function* test(testDriver) {
|
||||
var subframe = document.getElementById('scroll');
|
||||
|
||||
// scroll over the middle of the subframe, to make sure it scrolls,
|
||||
// not the page
|
||||
var scrollPos = subframe.scrollTop;
|
||||
yield moveMouseAndScrollWheelOver(subframe, 100, 100, testDriver);
|
||||
dump("after scroll, subframe.scrollTop = " + subframe.scrollTop + "\n");
|
||||
ok(subframe.scrollTop > scrollPos, "subframe scrolled after wheeling over it");
|
||||
}
|
||||
|
||||
waitUntilApzStable()
|
||||
.then(runContinuation(test))
|
||||
.then(subtestDone);
|
||||
|
||||
</script>
|
||||
<style>
|
||||
#scroll {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
overflow: scroll;
|
||||
perspective: 400px;
|
||||
}
|
||||
#scrolled {
|
||||
width: 200px;
|
||||
height: 1000px; /* so the subframe has room to scroll */
|
||||
background: linear-gradient(red, blue); /* so you can see it scroll */
|
||||
transform: translateZ(0px); /* so the perspective makes it to the display list */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="scroll">
|
||||
<div id="scrolled"></div>
|
||||
</div>
|
||||
<div style="height: 5000px;"></div><!-- So the page is scrollable as well -->
|
||||
</body>
|
||||
</head>
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
<head>
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Wheel-scrolling over inactive subframe with z-index</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function* test(testDriver) {
|
||||
var subframe = document.getElementById('scroll');
|
||||
|
||||
// scroll over the middle of the subframe, and make sure that it scrolls,
|
||||
// not the page
|
||||
var scrollPos = subframe.scrollTop;
|
||||
yield moveMouseAndScrollWheelOver(subframe, 100, 100, testDriver);
|
||||
dump("after scroll, subframe.scrollTop = " + subframe.scrollTop + "\n");
|
||||
ok(subframe.scrollTop > scrollPos, "subframe scrolled after wheeling over it");
|
||||
}
|
||||
|
||||
waitUntilApzStable()
|
||||
.then(runContinuation(test))
|
||||
.then(subtestDone);
|
||||
|
||||
</script>
|
||||
<style>
|
||||
#scroll {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
overflow: scroll;
|
||||
}
|
||||
#scrolled {
|
||||
width: 200px;
|
||||
height: 1000px; /* so the subframe has room to scroll */
|
||||
z-index: 2;
|
||||
background: linear-gradient(red, blue); /* so you can see it scroll */
|
||||
transform: translateZ(0px); /* to force active layers */
|
||||
will-change: transform; /* to force active layers */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="scroll">
|
||||
<div id="scrolled"></div>
|
||||
</div>
|
||||
<div style="height: 5000px;"></div><!-- So the page is scrollable as well -->
|
||||
</body>
|
||||
</head>
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<head>
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Wheel-scrolling over position:fixed and position:sticky elements, in the top-level document as well as iframes</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function* test(testDriver) {
|
||||
var iframeWin = document.getElementById('iframe').contentWindow;
|
||||
|
||||
// scroll over the middle of the iframe's position:sticky element, check
|
||||
// that it scrolls the iframe
|
||||
var scrollPos = iframeWin.scrollY;
|
||||
yield moveMouseAndScrollWheelOver(iframeWin.document.body, 50, 150, testDriver);
|
||||
ok(iframeWin.scrollY > scrollPos, "iframe scrolled after wheeling over the position:sticky element");
|
||||
|
||||
// same, but using the iframe's position:fixed element
|
||||
scrollPos = iframeWin.scrollY;
|
||||
yield moveMouseAndScrollWheelOver(iframeWin.document.body, 250, 150, testDriver);
|
||||
ok(iframeWin.scrollY > scrollPos, "iframe scrolled after wheeling over the position:fixed element");
|
||||
|
||||
// same, but scrolling the scrollable frame *inside* the position:fixed item
|
||||
var fpos = document.getElementById('fpos_scrollable');
|
||||
scrollPos = fpos.scrollTop;
|
||||
yield moveMouseAndScrollWheelOver(fpos, 50, 150, testDriver);
|
||||
ok(fpos.scrollTop > scrollPos, "scrollable item inside fixed-pos element scrolled");
|
||||
// wait for it to layerize fully and then try again
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
scrollPos = fpos.scrollTop;
|
||||
yield moveMouseAndScrollWheelOver(fpos, 50, 150, testDriver);
|
||||
ok(fpos.scrollTop > scrollPos, "scrollable item inside fixed-pos element scrolled after layerization");
|
||||
|
||||
// same, but using the top-level window's position:sticky element
|
||||
scrollPos = window.scrollY;
|
||||
yield moveMouseAndScrollWheelOver(document.body, 50, 150, testDriver);
|
||||
ok(window.scrollY > scrollPos, "top-level document scrolled after wheeling over the position:sticky element");
|
||||
|
||||
// same, but using the top-level window's position:fixed element
|
||||
scrollPos = window.scrollY;
|
||||
yield moveMouseAndScrollWheelOver(document.body, 250, 150, testDriver);
|
||||
ok(window.scrollY > scrollPos, "top-level document scrolled after wheeling over the position:fixed element");
|
||||
}
|
||||
|
||||
waitUntilApzStable()
|
||||
.then(runContinuation(test))
|
||||
.then(subtestDone);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body style="height:5000px; margin:0">
|
||||
<div style="position:sticky; width: 100px; height: 300px; top: 0; background-color:red">sticky</div>
|
||||
<div style="position:fixed; width: 100px; height: 300px; top: 0; left: 200px; background-color: green">fixed</div>
|
||||
<iframe id='iframe' width="300" height="400" src="data:text/html,<body style='height:5000px; margin:0'><div style='position:sticky; width:100px; height:300px; top: 0; background-color:red'>sticky</div><div style='position:fixed; right:0; top: 0; width:100px; height:300px; background-color:green'>fixed</div>"></iframe>
|
||||
|
||||
<div id="fpos_scrollable" style="position:fixed; width: 100px; height: 300px; top: 0; left: 400px; background-color: red; overflow:scroll">
|
||||
<div style="background-color: blue; height: 1000px; margin: 3px">scrollable content inside a fixed-pos item</div>
|
||||
</div>
|
||||
</body>
|
||||
</head>
|
||||
61
gfx/layers/apz/test/mochitest/helper_scrollto_tap.html
Normal file
61
gfx/layers/apz/test/mochitest/helper_scrollto_tap.html
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Sanity touch-tapping test</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function startTest() {
|
||||
if (window.scrollY == 0) {
|
||||
// the scrollframe is not yet marked as APZ-scrollable. Mark it so and
|
||||
// start over.
|
||||
window.scrollTo(0, 1);
|
||||
waitForApzFlushedRepaints(startTest);
|
||||
return;
|
||||
}
|
||||
|
||||
// This is a scroll by 20px that should use paint-skipping if possible.
|
||||
// If paint-skipping is enabled, this should not trigger a paint, but go
|
||||
// directly to the compositor using an empty transaction. We check for this
|
||||
// by ensuring the document element did not get painted.
|
||||
var utils = window.opener.SpecialPowers.getDOMWindowUtils(window);
|
||||
var elem = document.documentElement;
|
||||
var skipping = location.search == '?true';
|
||||
utils.checkAndClearPaintedState(elem);
|
||||
window.scrollTo(0, 20);
|
||||
waitForAllPaints(function() {
|
||||
if (skipping) {
|
||||
is(utils.checkAndClearPaintedState(elem), false, "Document element didn't get painted");
|
||||
}
|
||||
// After that's done, we click on the button to make sure the
|
||||
// skipped-paint codepath still has working APZ event transformations.
|
||||
clickButton();
|
||||
});
|
||||
}
|
||||
|
||||
function clickButton() {
|
||||
document.addEventListener('click', clicked, false);
|
||||
|
||||
synthesizeNativeTap(document.getElementById('b'), 5, 5, function() {
|
||||
dump("Finished synthesizing tap, waiting for button to be clicked...\n");
|
||||
});
|
||||
}
|
||||
|
||||
function clicked(e) {
|
||||
is(e.target, document.getElementById('b'), "Clicked on button, yay! (at " + e.clientX + "," + e.clientY + ")");
|
||||
subtestDone();
|
||||
}
|
||||
|
||||
waitUntilApzStable().then(startTest);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body style="height: 5000px">
|
||||
<div style="height: 50px">spacer</div>
|
||||
<button id="b" style="width: 10px; height: 10px"></button>
|
||||
</body>
|
||||
</html>
|
||||
15
gfx/layers/apz/test/mochitest/helper_subframe_style.css
Normal file
15
gfx/layers/apz/test/mochitest/helper_subframe_style.css
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
body {
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.inner-frame {
|
||||
margin-top: 50px; /* this should be at least 30px */
|
||||
height: 200%;
|
||||
width: 75%;
|
||||
overflow: scroll;
|
||||
}
|
||||
.inner-content {
|
||||
height: 200%;
|
||||
width: 200%;
|
||||
background: repeating-linear-gradient(#EEE, #EEE 100px, #DDD 100px, #DDD 200px);
|
||||
}
|
||||
504
gfx/layers/apz/test/mochitest/helper_tall.html
Normal file
504
gfx/layers/apz/test/mochitest/helper_tall.html
Normal file
|
|
@ -0,0 +1,504 @@
|
|||
<html id="tall_html">
|
||||
<body>
|
||||
This is a tall page<br/>
|
||||
1<br/>
|
||||
2<br/>
|
||||
3<br/>
|
||||
4<br/>
|
||||
5<br/>
|
||||
6<br/>
|
||||
7<br/>
|
||||
8<br/>
|
||||
9<br/>
|
||||
10<br/>
|
||||
11<br/>
|
||||
12<br/>
|
||||
13<br/>
|
||||
14<br/>
|
||||
15<br/>
|
||||
16<br/>
|
||||
17<br/>
|
||||
18<br/>
|
||||
19<br/>
|
||||
20<br/>
|
||||
21<br/>
|
||||
22<br/>
|
||||
23<br/>
|
||||
24<br/>
|
||||
25<br/>
|
||||
26<br/>
|
||||
27<br/>
|
||||
28<br/>
|
||||
29<br/>
|
||||
30<br/>
|
||||
31<br/>
|
||||
32<br/>
|
||||
33<br/>
|
||||
34<br/>
|
||||
35<br/>
|
||||
36<br/>
|
||||
37<br/>
|
||||
38<br/>
|
||||
39<br/>
|
||||
40<br/>
|
||||
41<br/>
|
||||
42<br/>
|
||||
43<br/>
|
||||
44<br/>
|
||||
45<br/>
|
||||
46<br/>
|
||||
47<br/>
|
||||
48<br/>
|
||||
49<br/>
|
||||
50<br/>
|
||||
51<br/>
|
||||
52<br/>
|
||||
53<br/>
|
||||
54<br/>
|
||||
55<br/>
|
||||
56<br/>
|
||||
57<br/>
|
||||
58<br/>
|
||||
59<br/>
|
||||
60<br/>
|
||||
61<br/>
|
||||
62<br/>
|
||||
63<br/>
|
||||
64<br/>
|
||||
65<br/>
|
||||
66<br/>
|
||||
67<br/>
|
||||
68<br/>
|
||||
69<br/>
|
||||
70<br/>
|
||||
71<br/>
|
||||
72<br/>
|
||||
73<br/>
|
||||
74<br/>
|
||||
75<br/>
|
||||
76<br/>
|
||||
77<br/>
|
||||
78<br/>
|
||||
79<br/>
|
||||
80<br/>
|
||||
81<br/>
|
||||
82<br/>
|
||||
83<br/>
|
||||
84<br/>
|
||||
85<br/>
|
||||
86<br/>
|
||||
87<br/>
|
||||
88<br/>
|
||||
89<br/>
|
||||
90<br/>
|
||||
91<br/>
|
||||
92<br/>
|
||||
93<br/>
|
||||
94<br/>
|
||||
95<br/>
|
||||
96<br/>
|
||||
97<br/>
|
||||
98<br/>
|
||||
99<br/>
|
||||
100<br/>
|
||||
101<br/>
|
||||
102<br/>
|
||||
103<br/>
|
||||
104<br/>
|
||||
105<br/>
|
||||
106<br/>
|
||||
107<br/>
|
||||
108<br/>
|
||||
109<br/>
|
||||
110<br/>
|
||||
111<br/>
|
||||
112<br/>
|
||||
113<br/>
|
||||
114<br/>
|
||||
115<br/>
|
||||
116<br/>
|
||||
117<br/>
|
||||
118<br/>
|
||||
119<br/>
|
||||
120<br/>
|
||||
121<br/>
|
||||
122<br/>
|
||||
123<br/>
|
||||
124<br/>
|
||||
125<br/>
|
||||
126<br/>
|
||||
127<br/>
|
||||
128<br/>
|
||||
129<br/>
|
||||
130<br/>
|
||||
131<br/>
|
||||
132<br/>
|
||||
133<br/>
|
||||
134<br/>
|
||||
135<br/>
|
||||
136<br/>
|
||||
137<br/>
|
||||
138<br/>
|
||||
139<br/>
|
||||
140<br/>
|
||||
141<br/>
|
||||
142<br/>
|
||||
143<br/>
|
||||
144<br/>
|
||||
145<br/>
|
||||
146<br/>
|
||||
147<br/>
|
||||
148<br/>
|
||||
149<br/>
|
||||
150<br/>
|
||||
151<br/>
|
||||
152<br/>
|
||||
153<br/>
|
||||
154<br/>
|
||||
155<br/>
|
||||
156<br/>
|
||||
157<br/>
|
||||
158<br/>
|
||||
159<br/>
|
||||
160<br/>
|
||||
161<br/>
|
||||
162<br/>
|
||||
163<br/>
|
||||
164<br/>
|
||||
165<br/>
|
||||
166<br/>
|
||||
167<br/>
|
||||
168<br/>
|
||||
169<br/>
|
||||
170<br/>
|
||||
171<br/>
|
||||
172<br/>
|
||||
173<br/>
|
||||
174<br/>
|
||||
175<br/>
|
||||
176<br/>
|
||||
177<br/>
|
||||
178<br/>
|
||||
179<br/>
|
||||
180<br/>
|
||||
181<br/>
|
||||
182<br/>
|
||||
183<br/>
|
||||
184<br/>
|
||||
185<br/>
|
||||
186<br/>
|
||||
187<br/>
|
||||
188<br/>
|
||||
189<br/>
|
||||
190<br/>
|
||||
191<br/>
|
||||
192<br/>
|
||||
193<br/>
|
||||
194<br/>
|
||||
195<br/>
|
||||
196<br/>
|
||||
197<br/>
|
||||
198<br/>
|
||||
199<br/>
|
||||
200<br/>
|
||||
201<br/>
|
||||
202<br/>
|
||||
203<br/>
|
||||
204<br/>
|
||||
205<br/>
|
||||
206<br/>
|
||||
207<br/>
|
||||
208<br/>
|
||||
209<br/>
|
||||
210<br/>
|
||||
211<br/>
|
||||
212<br/>
|
||||
213<br/>
|
||||
214<br/>
|
||||
215<br/>
|
||||
216<br/>
|
||||
217<br/>
|
||||
218<br/>
|
||||
219<br/>
|
||||
220<br/>
|
||||
221<br/>
|
||||
222<br/>
|
||||
223<br/>
|
||||
224<br/>
|
||||
225<br/>
|
||||
226<br/>
|
||||
227<br/>
|
||||
228<br/>
|
||||
229<br/>
|
||||
230<br/>
|
||||
231<br/>
|
||||
232<br/>
|
||||
233<br/>
|
||||
234<br/>
|
||||
235<br/>
|
||||
236<br/>
|
||||
237<br/>
|
||||
238<br/>
|
||||
239<br/>
|
||||
240<br/>
|
||||
241<br/>
|
||||
242<br/>
|
||||
243<br/>
|
||||
244<br/>
|
||||
245<br/>
|
||||
246<br/>
|
||||
247<br/>
|
||||
248<br/>
|
||||
249<br/>
|
||||
250<br/>
|
||||
251<br/>
|
||||
252<br/>
|
||||
253<br/>
|
||||
254<br/>
|
||||
255<br/>
|
||||
256<br/>
|
||||
257<br/>
|
||||
258<br/>
|
||||
259<br/>
|
||||
260<br/>
|
||||
261<br/>
|
||||
262<br/>
|
||||
263<br/>
|
||||
264<br/>
|
||||
265<br/>
|
||||
266<br/>
|
||||
267<br/>
|
||||
268<br/>
|
||||
269<br/>
|
||||
270<br/>
|
||||
271<br/>
|
||||
272<br/>
|
||||
273<br/>
|
||||
274<br/>
|
||||
275<br/>
|
||||
276<br/>
|
||||
277<br/>
|
||||
278<br/>
|
||||
279<br/>
|
||||
280<br/>
|
||||
281<br/>
|
||||
282<br/>
|
||||
283<br/>
|
||||
284<br/>
|
||||
285<br/>
|
||||
286<br/>
|
||||
287<br/>
|
||||
288<br/>
|
||||
289<br/>
|
||||
290<br/>
|
||||
291<br/>
|
||||
292<br/>
|
||||
293<br/>
|
||||
294<br/>
|
||||
295<br/>
|
||||
296<br/>
|
||||
297<br/>
|
||||
298<br/>
|
||||
299<br/>
|
||||
300<br/>
|
||||
301<br/>
|
||||
302<br/>
|
||||
303<br/>
|
||||
304<br/>
|
||||
305<br/>
|
||||
306<br/>
|
||||
307<br/>
|
||||
308<br/>
|
||||
309<br/>
|
||||
310<br/>
|
||||
311<br/>
|
||||
312<br/>
|
||||
313<br/>
|
||||
314<br/>
|
||||
315<br/>
|
||||
316<br/>
|
||||
317<br/>
|
||||
318<br/>
|
||||
319<br/>
|
||||
320<br/>
|
||||
321<br/>
|
||||
322<br/>
|
||||
323<br/>
|
||||
324<br/>
|
||||
325<br/>
|
||||
326<br/>
|
||||
327<br/>
|
||||
328<br/>
|
||||
329<br/>
|
||||
330<br/>
|
||||
331<br/>
|
||||
332<br/>
|
||||
333<br/>
|
||||
334<br/>
|
||||
335<br/>
|
||||
336<br/>
|
||||
337<br/>
|
||||
338<br/>
|
||||
339<br/>
|
||||
340<br/>
|
||||
341<br/>
|
||||
342<br/>
|
||||
343<br/>
|
||||
344<br/>
|
||||
345<br/>
|
||||
346<br/>
|
||||
347<br/>
|
||||
348<br/>
|
||||
349<br/>
|
||||
350<br/>
|
||||
351<br/>
|
||||
352<br/>
|
||||
353<br/>
|
||||
354<br/>
|
||||
355<br/>
|
||||
356<br/>
|
||||
357<br/>
|
||||
358<br/>
|
||||
359<br/>
|
||||
360<br/>
|
||||
361<br/>
|
||||
362<br/>
|
||||
363<br/>
|
||||
364<br/>
|
||||
365<br/>
|
||||
366<br/>
|
||||
367<br/>
|
||||
368<br/>
|
||||
369<br/>
|
||||
370<br/>
|
||||
371<br/>
|
||||
372<br/>
|
||||
373<br/>
|
||||
374<br/>
|
||||
375<br/>
|
||||
376<br/>
|
||||
377<br/>
|
||||
378<br/>
|
||||
379<br/>
|
||||
380<br/>
|
||||
381<br/>
|
||||
382<br/>
|
||||
383<br/>
|
||||
384<br/>
|
||||
385<br/>
|
||||
386<br/>
|
||||
387<br/>
|
||||
388<br/>
|
||||
389<br/>
|
||||
390<br/>
|
||||
391<br/>
|
||||
392<br/>
|
||||
393<br/>
|
||||
394<br/>
|
||||
395<br/>
|
||||
396<br/>
|
||||
397<br/>
|
||||
398<br/>
|
||||
399<br/>
|
||||
400<br/>
|
||||
401<br/>
|
||||
402<br/>
|
||||
403<br/>
|
||||
404<br/>
|
||||
405<br/>
|
||||
406<br/>
|
||||
407<br/>
|
||||
408<br/>
|
||||
409<br/>
|
||||
410<br/>
|
||||
411<br/>
|
||||
412<br/>
|
||||
413<br/>
|
||||
414<br/>
|
||||
415<br/>
|
||||
416<br/>
|
||||
417<br/>
|
||||
418<br/>
|
||||
419<br/>
|
||||
420<br/>
|
||||
421<br/>
|
||||
422<br/>
|
||||
423<br/>
|
||||
424<br/>
|
||||
425<br/>
|
||||
426<br/>
|
||||
427<br/>
|
||||
428<br/>
|
||||
429<br/>
|
||||
430<br/>
|
||||
431<br/>
|
||||
432<br/>
|
||||
433<br/>
|
||||
434<br/>
|
||||
435<br/>
|
||||
436<br/>
|
||||
437<br/>
|
||||
438<br/>
|
||||
439<br/>
|
||||
440<br/>
|
||||
441<br/>
|
||||
442<br/>
|
||||
443<br/>
|
||||
444<br/>
|
||||
445<br/>
|
||||
446<br/>
|
||||
447<br/>
|
||||
448<br/>
|
||||
449<br/>
|
||||
450<br/>
|
||||
451<br/>
|
||||
452<br/>
|
||||
453<br/>
|
||||
454<br/>
|
||||
455<br/>
|
||||
456<br/>
|
||||
457<br/>
|
||||
458<br/>
|
||||
459<br/>
|
||||
460<br/>
|
||||
461<br/>
|
||||
462<br/>
|
||||
463<br/>
|
||||
464<br/>
|
||||
465<br/>
|
||||
466<br/>
|
||||
467<br/>
|
||||
468<br/>
|
||||
469<br/>
|
||||
470<br/>
|
||||
471<br/>
|
||||
472<br/>
|
||||
473<br/>
|
||||
474<br/>
|
||||
475<br/>
|
||||
476<br/>
|
||||
477<br/>
|
||||
478<br/>
|
||||
479<br/>
|
||||
480<br/>
|
||||
481<br/>
|
||||
482<br/>
|
||||
483<br/>
|
||||
484<br/>
|
||||
485<br/>
|
||||
486<br/>
|
||||
487<br/>
|
||||
488<br/>
|
||||
489<br/>
|
||||
490<br/>
|
||||
491<br/>
|
||||
492<br/>
|
||||
493<br/>
|
||||
494<br/>
|
||||
495<br/>
|
||||
496<br/>
|
||||
497<br/>
|
||||
498<br/>
|
||||
499<br/>
|
||||
</body>
|
||||
</html>
|
||||
32
gfx/layers/apz/test/mochitest/helper_tap.html
Normal file
32
gfx/layers/apz/test/mochitest/helper_tap.html
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Sanity touch-tapping test</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function clickButton() {
|
||||
document.addEventListener('click', clicked, false);
|
||||
|
||||
synthesizeNativeTap(document.getElementById('b'), 5, 5, function() {
|
||||
dump("Finished synthesizing tap, waiting for button to be clicked...\n");
|
||||
});
|
||||
}
|
||||
|
||||
function clicked(e) {
|
||||
is(e.target, document.getElementById('b'), "Clicked on button, yay! (at " + e.clientX + "," + e.clientY + ")");
|
||||
subtestDone();
|
||||
}
|
||||
|
||||
waitUntilApzStable().then(clickButton);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<button id="b" style="width: 10px; height: 10px"></button>
|
||||
</body>
|
||||
</html>
|
||||
33
gfx/layers/apz/test/mochitest/helper_tap_fullzoom.html
Normal file
33
gfx/layers/apz/test/mochitest/helper_tap_fullzoom.html
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Sanity touch-tapping test with fullzoom</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function clickButton() {
|
||||
document.addEventListener('click', clicked, false);
|
||||
|
||||
synthesizeNativeTap(document.getElementById('b'), 5, 5, function() {
|
||||
dump("Finished synthesizing tap, waiting for button to be clicked...\n");
|
||||
});
|
||||
}
|
||||
|
||||
function clicked(e) {
|
||||
is(e.target, document.getElementById('b'), "Clicked on button, yay! (at " + e.clientX + "," + e.clientY + ")");
|
||||
subtestDone();
|
||||
}
|
||||
|
||||
SpecialPowers.setFullZoom(window, 2.0);
|
||||
waitUntilApzStable().then(clickButton);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<button id="b" style="width: 10px; height: 10px; position: relative; top: 100px"></button>
|
||||
</body>
|
||||
</html>
|
||||
64
gfx/layers/apz/test/mochitest/helper_tap_passive.html
Normal file
64
gfx/layers/apz/test/mochitest/helper_tap_passive.html
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Ensure APZ doesn't wait for passive listeners</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
var touchdownTime;
|
||||
|
||||
function longPressLink() {
|
||||
synthesizeNativeTouch(document.getElementById('b'), 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, function() {
|
||||
dump("Finished synthesizing touch-start, waiting for events...\n");
|
||||
});
|
||||
}
|
||||
|
||||
var touchstartReceived = false;
|
||||
function recordEvent(e) {
|
||||
if (!touchstartReceived) {
|
||||
touchstartReceived = true;
|
||||
is(e.type, 'touchstart', 'Got a touchstart');
|
||||
e.preventDefault(); // should be a no-op because it's a passive listener
|
||||
return;
|
||||
}
|
||||
|
||||
// If APZ decides to wait for the content response on a particular input block,
|
||||
// it needs to wait until both the touchstart and touchmove event are handled
|
||||
// by the main thread. In this case there is no touchmove at all, so APZ would
|
||||
// end up waiting indefinitely and time out the test. The fact that we get this
|
||||
// contextmenu event (mouselongtap on Windows) at all means that APZ decided
|
||||
// not to wait for the content response, which is the desired behaviour, since
|
||||
// the touchstart listener was registered as a passive listener.
|
||||
if (getPlatform() == "windows") {
|
||||
is(e.type, 'mouselongtap', 'Got a mouselongtap');
|
||||
} else {
|
||||
is(e.type, 'contextmenu', 'Got a contextmenu');
|
||||
}
|
||||
e.preventDefault();
|
||||
|
||||
synthesizeNativeTouch(document.getElementById('b'), 5, 5, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, function() {
|
||||
dump("Finished synthesizing touch-end to clear state; finishing test...\n");
|
||||
subtestDone();
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener('touchstart', recordEvent, { passive: true, capture: true });
|
||||
if (getPlatform() == "windows") {
|
||||
SpecialPowers.addChromeEventListener('mouselongtap', recordEvent, true);
|
||||
} else {
|
||||
window.addEventListener('contextmenu', recordEvent, true);
|
||||
}
|
||||
|
||||
waitUntilApzStable()
|
||||
.then(longPressLink);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a id="b" href="#">Link to nowhere</a>
|
||||
</body>
|
||||
</html>
|
||||
115
gfx/layers/apz/test/mochitest/helper_touch_action.html
Normal file
115
gfx/layers/apz/test/mochitest/helper_touch_action.html
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Sanity touch-action test</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function checkScroll(x, y, desc) {
|
||||
is(window.scrollX, x, desc + " - x axis");
|
||||
is(window.scrollY, y, desc + " - y axis");
|
||||
}
|
||||
|
||||
function* test(testDriver) {
|
||||
var target = document.getElementById('target');
|
||||
|
||||
document.body.addEventListener('touchend', testDriver, { passive: true });
|
||||
|
||||
// drag the page up to scroll down by 50px
|
||||
yield ok(synthesizeNativeTouchDrag(target, 10, 100, 0, -(50 + TOUCH_SLOP)),
|
||||
"Synthesized native vertical drag (1), waiting for touch-end event...");
|
||||
yield flushApzRepaints(testDriver);
|
||||
checkScroll(0, 50, "After first vertical drag, with pan-y" );
|
||||
|
||||
// switch style to pan-x
|
||||
document.body.style.touchAction = 'pan-x';
|
||||
ok(true, "Waiting for pan-x to propagate...");
|
||||
yield waitForAllPaintsFlushed(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
|
||||
// drag the page up to scroll down by 50px, but it won't happen because pan-x
|
||||
yield ok(synthesizeNativeTouchDrag(target, 10, 100, 0, -(50 + TOUCH_SLOP)),
|
||||
"Synthesized native vertical drag (2), waiting for touch-end event...");
|
||||
yield flushApzRepaints(testDriver);
|
||||
checkScroll(0, 50, "After second vertical drag, with pan-x");
|
||||
|
||||
// drag the page left to scroll right by 50px
|
||||
yield ok(synthesizeNativeTouchDrag(target, 100, 10, -(50 + TOUCH_SLOP), 0),
|
||||
"Synthesized horizontal drag (1), waiting for touch-end event...");
|
||||
yield flushApzRepaints(testDriver);
|
||||
checkScroll(50, 50, "After first horizontal drag, with pan-x");
|
||||
|
||||
// drag the page diagonally right/down to scroll up/left by 40px each axis;
|
||||
// only the x-axis will actually scroll because pan-x
|
||||
yield ok(synthesizeNativeTouchDrag(target, 10, 10, (40 + TOUCH_SLOP), (40 + TOUCH_SLOP)),
|
||||
"Synthesized diagonal drag (1), waiting for touch-end event...");
|
||||
yield flushApzRepaints(testDriver);
|
||||
checkScroll(10, 50, "After first diagonal drag, with pan-x");
|
||||
|
||||
// switch style back to pan-y
|
||||
document.body.style.touchAction = 'pan-y';
|
||||
ok(true, "Waiting for pan-y to propagate...");
|
||||
yield waitForAllPaintsFlushed(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
|
||||
// drag the page diagonally right/down to scroll up/left by 40px each axis;
|
||||
// only the y-axis will actually scroll because pan-y
|
||||
yield ok(synthesizeNativeTouchDrag(target, 10, 10, (40 + TOUCH_SLOP), (40 + TOUCH_SLOP)),
|
||||
"Synthesized diagonal drag (2), waiting for touch-end event...");
|
||||
yield flushApzRepaints(testDriver);
|
||||
checkScroll(10, 10, "After second diagonal drag, with pan-y");
|
||||
|
||||
// switch style to none
|
||||
document.body.style.touchAction = 'none';
|
||||
ok(true, "Waiting for none to propagate...");
|
||||
yield waitForAllPaintsFlushed(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
|
||||
// drag the page diagonally up/left to scroll down/right by 40px each axis;
|
||||
// neither will scroll because of touch-action
|
||||
yield ok(synthesizeNativeTouchDrag(target, 100, 100, -(40 + TOUCH_SLOP), -(40 + TOUCH_SLOP)),
|
||||
"Synthesized diagonal drag (3), waiting for touch-end event...");
|
||||
yield flushApzRepaints(testDriver);
|
||||
checkScroll(10, 10, "After third diagonal drag, with none");
|
||||
|
||||
document.body.style.touchAction = 'manipulation';
|
||||
ok(true, "Waiting for manipulation to propagate...");
|
||||
yield waitForAllPaintsFlushed(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
|
||||
// drag the page diagonally up/left to scroll down/right by 40px each axis;
|
||||
// both will scroll because of touch-action
|
||||
yield ok(synthesizeNativeTouchDrag(target, 100, 100, -(40 + TOUCH_SLOP), -(40 + TOUCH_SLOP)),
|
||||
"Synthesized diagonal drag (4), waiting for touch-end event...");
|
||||
yield flushApzRepaints(testDriver);
|
||||
checkScroll(50, 50, "After fourth diagonal drag, with manipulation");
|
||||
}
|
||||
|
||||
waitUntilApzStable()
|
||||
.then(runContinuation(test))
|
||||
.then(subtestDone);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body style="touch-action: pan-y">
|
||||
<div style="width: 5000px; height: 5000px; background-color: lightgreen;">
|
||||
This div makes the page scrollable on both axes.<br>
|
||||
This is the second line of text.<br>
|
||||
This is the third line of text.<br>
|
||||
This is the fourth line of text.
|
||||
</div>
|
||||
<!-- This fixed-position div remains in the same place relative to the browser chrome, so we
|
||||
can use it as a targeting device for synthetic touch events. The body will move around
|
||||
as we scroll, so we'd have to be constantly adjusting the synthetic drag coordinates
|
||||
if we used that as the target element. -->
|
||||
<div style="position:fixed; left: 10px; top: 10px; width: 1px; height: 1px" id="target"></div>
|
||||
</body>
|
||||
</html>
|
||||
143
gfx/layers/apz/test/mochitest/helper_touch_action_complex.html
Normal file
143
gfx/layers/apz/test/mochitest/helper_touch_action_complex.html
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Complex touch-action test</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function checkScroll(target, x, y, desc) {
|
||||
is(target.scrollLeft, x, desc + " - x axis");
|
||||
is(target.scrollTop, y, desc + " - y axis");
|
||||
}
|
||||
|
||||
function resetConfiguration(config, testDriver) {
|
||||
// Cycle through all the configuration_X elements, setting them to display:none
|
||||
// except for when X == config, in which case set it to display:block
|
||||
var i = 0;
|
||||
while (true) {
|
||||
i++;
|
||||
var element = document.getElementById('configuration_' + i);
|
||||
if (element == null) {
|
||||
if (i <= config) {
|
||||
ok(false, "The configuration requested was not encountered!");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == config) {
|
||||
element.style.display = 'block';
|
||||
} else {
|
||||
element.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Also reset the scroll position on the scrollframe
|
||||
var s = document.getElementById('scrollframe');
|
||||
s.scrollLeft = 0;
|
||||
s.scrollTop = 0;
|
||||
|
||||
return waitForAllPaints(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
}
|
||||
|
||||
function* test(testDriver) {
|
||||
var scrollframe = document.getElementById('scrollframe');
|
||||
|
||||
document.body.addEventListener('touchend', testDriver, { passive: true });
|
||||
|
||||
// Helper function for the tests below.
|
||||
// Touch-pan configuration |configuration| towards scroll offset (dx, dy) with
|
||||
// the pan touching down at (x, y). Check that the final scroll offset is
|
||||
// (ex, ey). |desc| is some description string.
|
||||
function* scrollAndCheck(configuration, x, y, dx, dy, ex, ey, desc) {
|
||||
// Start with a clean slate
|
||||
yield resetConfiguration(configuration, testDriver);
|
||||
// Figure out the panning deltas
|
||||
if (dx != 0) {
|
||||
dx = -(dx + TOUCH_SLOP);
|
||||
}
|
||||
if (dy != 0) {
|
||||
dy = -(dy + TOUCH_SLOP);
|
||||
}
|
||||
// Do the pan
|
||||
yield ok(synthesizeNativeTouchDrag(scrollframe, x, y, dx, dy),
|
||||
"Synthesized drag of (" + dx + ", " + dy + ") on configuration " + configuration);
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
// Check for expected scroll position
|
||||
checkScroll(scrollframe, ex, ey, 'configuration ' + configuration + ' ' + desc);
|
||||
}
|
||||
|
||||
// Test configuration_1, which contains two sibling elements that are
|
||||
// overlapping. The touch-action from the second sibling (which is on top)
|
||||
// should be used for the overlapping area.
|
||||
yield* scrollAndCheck(1, 25, 75, 20, 0, 20, 0, "first element horizontal scroll");
|
||||
yield* scrollAndCheck(1, 25, 75, 0, 50, 0, 0, "first element vertical scroll");
|
||||
yield* scrollAndCheck(1, 75, 75, 50, 0, 0, 0, "overlap horizontal scroll");
|
||||
yield* scrollAndCheck(1, 75, 75, 0, 50, 0, 50, "overlap vertical scroll");
|
||||
yield* scrollAndCheck(1, 125, 75, 20, 0, 0, 0, "second element horizontal scroll");
|
||||
yield* scrollAndCheck(1, 125, 75, 0, 50, 0, 50, "second element vertical scroll");
|
||||
|
||||
// Test configuration_2, which contains two overlapping elements with a
|
||||
// parent/child relationship. The parent has pan-x and the child has pan-y,
|
||||
// which means that panning on the parent should work horizontally only, and
|
||||
// on the child no panning should occur at all.
|
||||
yield* scrollAndCheck(2, 125, 125, 50, 50, 0, 0, "child scroll");
|
||||
yield* scrollAndCheck(2, 75, 75, 50, 50, 0, 0, "overlap scroll");
|
||||
yield* scrollAndCheck(2, 25, 75, 0, 50, 0, 0, "parent vertical scroll");
|
||||
yield* scrollAndCheck(2, 75, 25, 50, 0, 50, 0, "parent horizontal scroll");
|
||||
|
||||
// Test configuration_3, which is the same as configuration_2, except the child
|
||||
// has a rotation transform applied. This forces the event regions on the two
|
||||
// elements to be built separately and then get merged.
|
||||
yield* scrollAndCheck(3, 125, 125, 50, 50, 0, 0, "child scroll");
|
||||
yield* scrollAndCheck(3, 75, 75, 50, 50, 0, 0, "overlap scroll");
|
||||
yield* scrollAndCheck(3, 25, 75, 0, 50, 0, 0, "parent vertical scroll");
|
||||
yield* scrollAndCheck(3, 75, 25, 50, 0, 50, 0, "parent horizontal scroll");
|
||||
|
||||
// Test configuration_4 has two elements, one above the other, not overlapping,
|
||||
// and the second element is a child of the first. The parent has pan-x, the
|
||||
// child has pan-y, but that means panning horizontally on the parent should
|
||||
// work and panning in any direction on the child should not do anything.
|
||||
yield* scrollAndCheck(4, 75, 75, 50, 50, 50, 0, "parent diagonal scroll");
|
||||
yield* scrollAndCheck(4, 75, 150, 50, 50, 0, 0, "child diagonal scroll");
|
||||
}
|
||||
|
||||
waitUntilApzStable()
|
||||
.then(runContinuation(test))
|
||||
.then(subtestDone);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="scrollframe" style="width: 300px; height: 300px; overflow:scroll">
|
||||
<div id="scrolled_content" style="width: 1000px; height: 1000px; background-color: green">
|
||||
</div>
|
||||
<div id="configuration_1" style="display:none; position: relative; top: -1000px">
|
||||
<div style="touch-action: pan-x; width: 100px; height: 100px; background-color: blue"></div>
|
||||
<div style="touch-action: pan-y; width: 100px; height: 100px; position: relative; top: -100px; left: 50px; background-color: yellow"></div>
|
||||
</div>
|
||||
<div id="configuration_2" style="display:none; position: relative; top: -1000px">
|
||||
<div style="touch-action: pan-x; width: 100px; height: 100px; background-color: blue">
|
||||
<div style="touch-action: pan-y; width: 100px; height: 100px; position: relative; top: 50px; left: 50px; background-color: yellow"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="configuration_3" style="display:none; position: relative; top: -1000px">
|
||||
<div style="touch-action: pan-x; width: 100px; height: 100px; background-color: blue">
|
||||
<div style="touch-action: pan-y; width: 100px; height: 100px; position: relative; top: 50px; left: 50px; background-color: yellow; transform: rotate(90deg)"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="configuration_4" style="display:none; position: relative; top: -1000px">
|
||||
<div style="touch-action: pan-x; width: 100px; height: 100px; background-color: blue">
|
||||
<div style="touch-action: pan-y; width: 100px; height: 100px; position: relative; top: 125px; background-color: yellow"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
246
gfx/layers/apz/test/mochitest/helper_touch_action_regions.html
Normal file
246
gfx/layers/apz/test/mochitest/helper_touch_action_regions.html
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Test to ensure APZ doesn't always wait for touch-action</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function failure(e) {
|
||||
ok(false, "This event listener should not have triggered: " + e.type);
|
||||
}
|
||||
|
||||
function success(e) {
|
||||
success.triggered = true;
|
||||
}
|
||||
|
||||
// This helper function provides a way for the child process to synchronously
|
||||
// check how many touch events the chrome process main-thread has processed. This
|
||||
// function can be called with three values: 'start', 'report', and 'end'.
|
||||
// The 'start' invocation sets up the listeners, and should be invoked before
|
||||
// the touch events of interest are generated. This should only be called once.
|
||||
// This returns true on success, and false on failure.
|
||||
// The 'report' invocation can be invoked multiple times, and returns an object
|
||||
// (in JSON string format) containing the counters.
|
||||
// The 'end' invocation tears down the listeners, and should be invoked once
|
||||
// at the end to clean up. Returns true on success, false on failure.
|
||||
function chromeTouchEventCounter(operation) {
|
||||
function chromeProcessCounter() {
|
||||
addMessageListener('start', function() {
|
||||
Components.utils.import('resource://gre/modules/Services.jsm');
|
||||
var topWin = Services.wm.getMostRecentWindow('navigator:browser');
|
||||
if (typeof topWin.eventCounts != 'undefined') {
|
||||
dump('Found pre-existing eventCounts object on the top window!\n');
|
||||
return false;
|
||||
}
|
||||
topWin.eventCounts = { 'touchstart': 0, 'touchmove': 0, 'touchend': 0 };
|
||||
topWin.counter = function(e) {
|
||||
topWin.eventCounts[e.type]++;
|
||||
}
|
||||
|
||||
topWin.addEventListener('touchstart', topWin.counter, { passive: true });
|
||||
topWin.addEventListener('touchmove', topWin.counter, { passive: true });
|
||||
topWin.addEventListener('touchend', topWin.counter, { passive: true });
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
addMessageListener('report', function() {
|
||||
Components.utils.import('resource://gre/modules/Services.jsm');
|
||||
var topWin = Services.wm.getMostRecentWindow('navigator:browser');
|
||||
return JSON.stringify(topWin.eventCounts);
|
||||
});
|
||||
|
||||
addMessageListener('end', function() {
|
||||
Components.utils.import('resource://gre/modules/Services.jsm');
|
||||
var topWin = Services.wm.getMostRecentWindow('navigator:browser');
|
||||
if (typeof topWin.eventCounts == 'undefined') {
|
||||
dump('The eventCounts object was not found on the top window!\n');
|
||||
return false;
|
||||
}
|
||||
topWin.removeEventListener('touchstart', topWin.counter);
|
||||
topWin.removeEventListener('touchmove', topWin.counter);
|
||||
topWin.removeEventListener('touchend', topWin.counter);
|
||||
delete topWin.counter;
|
||||
delete topWin.eventCounts;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof chromeTouchEventCounter.chromeHelper == 'undefined') {
|
||||
// This is the first time getSnapshot is being called; do initialization
|
||||
chromeTouchEventCounter.chromeHelper = SpecialPowers.loadChromeScript(chromeProcessCounter);
|
||||
SimpleTest.registerCleanupFunction(function() { chromeTouchEventCounter.chromeHelper.destroy() });
|
||||
}
|
||||
|
||||
return chromeTouchEventCounter.chromeHelper.sendSyncMessage(operation, "");
|
||||
}
|
||||
|
||||
// Simple wrapper that waits until the chrome process has seen |count| instances
|
||||
// of the |eventType| event. Returns true on success, and false if 10 seconds
|
||||
// go by without the condition being satisfied.
|
||||
function waitFor(eventType, count) {
|
||||
var start = Date.now();
|
||||
while (JSON.parse(chromeTouchEventCounter('report'))[eventType] != count) {
|
||||
if (Date.now() - start > 10000) {
|
||||
// It's taking too long, let's abort
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function* test(testDriver) {
|
||||
// The main part of this test should run completely before the child process'
|
||||
// main-thread deals with the touch event, so check to make sure that happens.
|
||||
document.body.addEventListener('touchstart', failure, { passive: true });
|
||||
|
||||
// What we want here is to synthesize all of the touch events (from this code in
|
||||
// the child process), and have the chrome process generate and process them,
|
||||
// but not allow the events to be dispatched back into the child process until
|
||||
// later. This allows us to ensure that the APZ in the chrome process is not
|
||||
// waiting for the child process to send notifications upon processing the
|
||||
// events. If it were doing so, the APZ would block and this test would fail.
|
||||
|
||||
// In order to actually implement this, we call the synthesize functions with
|
||||
// a async callback in between. The synthesize functions just queue up a
|
||||
// runnable on the child process main thread and return immediately, so with
|
||||
// the async callbacks, the child process main thread queue looks like
|
||||
// this after we're done setting it up:
|
||||
// synthesizeTouchStart
|
||||
// callback testDriver
|
||||
// synthesizeTouchMove
|
||||
// callback testDriver
|
||||
// ...
|
||||
// synthesizeTouchEnd
|
||||
// callback testDriver
|
||||
//
|
||||
// If, after setting up this queue, we yield once, the first synthesization and
|
||||
// callback will run - this will send a synthesization message to the chrome
|
||||
// process, and return control back to us right away. When the chrome process
|
||||
// processes with the synthesized event, it will dispatch the DOM touch event
|
||||
// back to the child process over IPC, which will go into the end of the child
|
||||
// process main thread queue, like so:
|
||||
// synthesizeTouchStart (done)
|
||||
// invoke testDriver (done)
|
||||
// synthesizeTouchMove
|
||||
// invoke testDriver
|
||||
// ...
|
||||
// synthesizeTouchEnd
|
||||
// invoke testDriver
|
||||
// handle DOM touchstart <-- touchstart goes at end of queue
|
||||
//
|
||||
// As we continue yielding one at a time, the synthesizations run, and the
|
||||
// touch events get added to the end of the queue. As we yield, we take
|
||||
// snapshots in the chrome process, to make sure that the APZ has started
|
||||
// scrolling even though we know we haven't yet processed the DOM touch events
|
||||
// in the child process yet.
|
||||
//
|
||||
// Note that the "async callback" we use here is SpecialPowers.executeSoon,
|
||||
// because nothing else does exactly what we want:
|
||||
// - setTimeout(..., 0) does not maintain ordering, because it respects the
|
||||
// time delta provided (i.e. the callback can jump the queue to meet its
|
||||
// deadline).
|
||||
// - SpecialPowers.spinEventLoop and SpecialPowers.executeAfterFlushingMessageQueue
|
||||
// are not e10s friendly, and can get arbitrarily delayed due to IPC
|
||||
// round-trip time.
|
||||
// - SimpleTest.executeSoon has a codepath that delegates to setTimeout, so
|
||||
// is less reliable if it ever decides to switch to that codepath.
|
||||
|
||||
// The other problem we need to deal with is the asynchronicity in the chrome
|
||||
// process. That is, we might request a snapshot before the chrome process has
|
||||
// actually synthesized the event and processed it. To guard against this, we
|
||||
// register a thing in the chrome process that counts the touch events that
|
||||
// have been dispatched, and poll that thing synchronously in order to make
|
||||
// sure we only snapshot after the event in question has been processed.
|
||||
// That's what the chromeTouchEventCounter business is all about. The sync
|
||||
// polling looks bad but in practice only ends up needing to poll once or
|
||||
// twice before the condition is satisfied, and as an extra precaution we add
|
||||
// a time guard so it fails after 10s of polling.
|
||||
|
||||
// So, here we go...
|
||||
|
||||
// Set up the chrome process touch listener
|
||||
ok(chromeTouchEventCounter('start'), "Chrome touch counter registered");
|
||||
|
||||
// Set up the child process events and callbacks
|
||||
var scroller = document.getElementById('scroller');
|
||||
synthesizeNativeTouch(scroller, 10, 110, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, null, 0);
|
||||
SpecialPowers.executeSoon(testDriver);
|
||||
for (var i = 1; i < 10; i++) {
|
||||
synthesizeNativeTouch(scroller, 10, 110 - (i * 10), SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, null, 0);
|
||||
SpecialPowers.executeSoon(testDriver);
|
||||
}
|
||||
synthesizeNativeTouch(scroller, 10, 10, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, null, 0);
|
||||
SpecialPowers.executeSoon(testDriver);
|
||||
ok(true, "Finished setting up event queue");
|
||||
|
||||
// Get our baseline snapshot
|
||||
var rect = rectRelativeToScreen(scroller);
|
||||
var lastSnapshot = getSnapshot(rect);
|
||||
ok(true, "Got baseline snapshot");
|
||||
|
||||
yield; // this will tell the chrome process to synthesize the touchstart event
|
||||
// and then we wait to make sure it got processed:
|
||||
ok(waitFor('touchstart', 1), "Touchstart processed in chrome process");
|
||||
|
||||
// Loop through the touchmove events
|
||||
for (var i = 1; i < 10; i++) {
|
||||
yield;
|
||||
ok(waitFor('touchmove', i), "Touchmove processed in chrome process");
|
||||
|
||||
var snapshot = getSnapshot(rect);
|
||||
if (i == 1) {
|
||||
// The first touchmove is consumed to get us into the panning state, so
|
||||
// no actual panning occurs
|
||||
ok(lastSnapshot == snapshot, "Snapshot 1 was the same as baseline");
|
||||
} else {
|
||||
ok(lastSnapshot != snapshot, "Snapshot " + i + " was different from the previous one");
|
||||
}
|
||||
lastSnapshot = snapshot;
|
||||
}
|
||||
|
||||
// Wait for the touchend as well, just for good form
|
||||
yield;
|
||||
ok(waitFor('touchend', 1), "Touchend processed in chrome process");
|
||||
|
||||
// Clean up the chrome process hooks
|
||||
chromeTouchEventCounter('end');
|
||||
|
||||
// Now we are going to release our grip on the child process main thread,
|
||||
// so that all the DOM events that were queued up can be processed. We
|
||||
// register a touchstart listener to make sure this happens.
|
||||
document.body.removeEventListener('touchstart', failure);
|
||||
document.body.addEventListener('touchstart', success, { passive: true });
|
||||
yield flushApzRepaints(testDriver);
|
||||
ok(success.triggered, "The touchstart event handler was triggered after snapshotting completed");
|
||||
document.body.removeEventListener('touchstart', success);
|
||||
}
|
||||
|
||||
if (SpecialPowers.isMainProcess()) {
|
||||
// This is probably android, where everything is single-process. The
|
||||
// test structure depends on e10s, so the test won't run properly on
|
||||
// this platform. Skip it
|
||||
ok(true, "Skipping test because it is designed to run from the content process");
|
||||
subtestDone();
|
||||
} else {
|
||||
waitUntilApzStable()
|
||||
.then(runContinuation(test))
|
||||
.then(subtestDone);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="scroller" style="width: 400px; height: 400px; overflow: scroll; touch-action: pan-y">
|
||||
<div style="width: 200px; height: 200px; background-color: lightgreen;">
|
||||
This is a colored div that will move on the screen as the scroller scrolls.
|
||||
</div>
|
||||
<div style="width: 1000px; height: 1000px; background-color: lightblue">
|
||||
This is a large div to make the scroller scrollable.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
67
gfx/layers/apz/test/mochitest/mochitest.ini
Normal file
67
gfx/layers/apz/test/mochitest/mochitest.ini
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
apz_test_native_event_utils.js
|
||||
apz_test_utils.js
|
||||
helper_basic_pan.html
|
||||
helper_bug982141.html
|
||||
helper_bug1151663.html
|
||||
helper_bug1162771.html
|
||||
helper_bug1271432.html
|
||||
helper_bug1280013.html
|
||||
helper_bug1285070.html
|
||||
helper_bug1299195.html
|
||||
helper_click.html
|
||||
helper_div_pan.html
|
||||
helper_drag_click.html
|
||||
helper_drag_scroll.html
|
||||
helper_iframe_pan.html
|
||||
helper_iframe1.html
|
||||
helper_iframe2.html
|
||||
helper_long_tap.html
|
||||
helper_scroll_inactive_perspective.html
|
||||
helper_scroll_inactive_zindex.html
|
||||
helper_scroll_on_position_fixed.html
|
||||
helper_scrollto_tap.html
|
||||
helper_subframe_style.css
|
||||
helper_tall.html
|
||||
helper_tap.html
|
||||
helper_tap_fullzoom.html
|
||||
helper_tap_passive.html
|
||||
helper_touch_action.html
|
||||
helper_touch_action_regions.html
|
||||
helper_touch_action_complex.html
|
||||
tags = apz
|
||||
[test_bug982141.html]
|
||||
[test_bug1151663.html]
|
||||
[test_bug1151667.html]
|
||||
skip-if = (os == 'android') # wheel events not supported on mobile
|
||||
[test_bug1253683.html]
|
||||
skip-if = (os == 'android') # wheel events not supported on mobile
|
||||
[test_bug1277814.html]
|
||||
skip-if = (os == 'android') # wheel events not supported on mobile
|
||||
[test_bug1304689.html]
|
||||
[test_bug1304689-2.html]
|
||||
[test_frame_reconstruction.html]
|
||||
[test_group_mouseevents.html]
|
||||
skip-if = (toolkit == 'android') # mouse events not supported on mobile
|
||||
[test_group_pointerevents.html]
|
||||
[test_group_touchevents.html]
|
||||
[test_group_wheelevents.html]
|
||||
skip-if = (toolkit == 'android') # wheel events not supported on mobile
|
||||
[test_group_zoom.html]
|
||||
skip-if = (toolkit != 'android') # only android supports zoom
|
||||
[test_interrupted_reflow.html]
|
||||
[test_layerization.html]
|
||||
skip-if = (os == 'android') # wheel events not supported on mobile
|
||||
[test_scroll_inactive_bug1190112.html]
|
||||
skip-if = (os == 'android') # wheel events not supported on mobile
|
||||
[test_scroll_inactive_flattened_frame.html]
|
||||
skip-if = (os == 'android') # wheel events not supported on mobile
|
||||
[test_scroll_subframe_scrollbar.html]
|
||||
skip-if = (os == 'android') # wheel events not supported on mobile
|
||||
[test_touch_listeners_impacting_wheel.html]
|
||||
skip-if = (toolkit == 'android') || (toolkit == 'cocoa') # wheel events not supported on mobile, and synthesized wheel smooth-scrolling not supported on OS X
|
||||
[test_wheel_scroll.html]
|
||||
skip-if = (os == 'android') # wheel events not supported on mobile
|
||||
[test_wheel_transactions.html]
|
||||
skip-if = (os == 'android') # wheel events not supported on mobile
|
||||
38
gfx/layers/apz/test/mochitest/test_bug1151663.html
Normal file
38
gfx/layers/apz/test/mochitest/test_bug1151663.html
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1151663
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1151663</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
if (isApzEnabled()) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Run the actual test in its own window, because it requires that the
|
||||
// root APZC be scrollable. Mochitest pages themselves often run
|
||||
// inside an iframe which means we have no control over the root APZC.
|
||||
var w = null;
|
||||
window.onload = function() {
|
||||
pushPrefs([["apz.test.logging_enabled", true]]).then(function() {
|
||||
w = window.open("helper_bug1151663.html", "_blank");
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function finishTest() {
|
||||
w.close();
|
||||
SimpleTest.finish();
|
||||
};
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1151663">Mozilla Bug 1151663</a>
|
||||
</body>
|
||||
</html>
|
||||
65
gfx/layers/apz/test/mochitest/test_bug1151667.html
Normal file
65
gfx/layers/apz/test/mochitest/test_bug1151667.html
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1151667
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1151667</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
#subframe {
|
||||
margin-top: 100px;
|
||||
height: 500px;
|
||||
width: 500px;
|
||||
overflow: scroll;
|
||||
}
|
||||
#subframe-content {
|
||||
height: 1000px;
|
||||
width: 500px;
|
||||
/* the background is so that we can see it scroll*/
|
||||
background: repeating-linear-gradient(#EEE, #EEE 100px, #DDD 100px, #DDD 200px);
|
||||
}
|
||||
#page-content {
|
||||
height: 5000px;
|
||||
width: 500px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1151667">Mozilla Bug 1151667</a>
|
||||
<p id="display"></p>
|
||||
<div id="subframe">
|
||||
<!-- This makes sure the subframe is scrollable -->
|
||||
<div id="subframe-content"></div>
|
||||
</div>
|
||||
<!-- This makes sure the page is also scrollable, so it (rather than the subframe)
|
||||
is considered the primary async-scrollable frame, and so the subframe isn't
|
||||
layerized upon page load. -->
|
||||
<div id="page-content"></div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function startTest() {
|
||||
var subframe = document.getElementById('subframe');
|
||||
synthesizeNativeWheelAndWaitForScrollEvent(subframe, 100, 150, 0, -10, continueTest);
|
||||
}
|
||||
|
||||
function continueTest() {
|
||||
var subframe = document.getElementById('subframe');
|
||||
is(subframe.scrollTop > 0, true, "We should have scrolled the subframe down");
|
||||
is(document.documentElement.scrollTop, 0, "We should not have scrolled the page");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
waitUntilApzStable().then(startTest);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
59
gfx/layers/apz/test/mochitest/test_bug1253683.html
Normal file
59
gfx/layers/apz/test/mochitest/test_bug1253683.html
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1253683
|
||||
-->
|
||||
<head>
|
||||
<title>Test to ensure non-scrollable frames don't get layerized</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="container" style="height: 500px; overflow:scroll">
|
||||
<pre id="no_layer" style="background-color: #f5f5f5; margin: 15px; padding: 15px; margin-top: 100px; border: 1px solid #eee; overflow:scroll">sample code here</pre>
|
||||
<div style="height: 5000px">spacer to make the 'container' div the root scrollable element</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function* test(testDriver) {
|
||||
var container = document.getElementById('container');
|
||||
var no_layer = document.getElementById('no_layer');
|
||||
|
||||
// Check initial state
|
||||
is(container.scrollTop, 0, "Initial scrollY should be 0");
|
||||
ok(!isLayerized('no_layer'), "initially 'no_layer' should not be layerized");
|
||||
|
||||
// Scrolling over outer1 should layerize outer1, but not inner1.
|
||||
yield moveMouseAndScrollWheelOver(no_layer, 10, 10, testDriver, true);
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
|
||||
ok(container.scrollTop > 0, "We should have scrolled the body");
|
||||
ok(!isLayerized('no_layer'), "no_layer should still not be layerized");
|
||||
}
|
||||
|
||||
if (isApzEnabled()) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Turn off displayport expiry so that we don't miss failures where the
|
||||
// displayport is set and expired before we check for layerization.
|
||||
// Also enable APZ test logging, since we use that data to determine whether
|
||||
// a scroll frame was layerized.
|
||||
pushPrefs([["apz.displayport_expiry_ms", 0],
|
||||
["apz.test.logging_enabled", true]])
|
||||
.then(waitUntilApzStable)
|
||||
.then(runContinuation(test))
|
||||
.then(SimpleTest.finish);
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
106
gfx/layers/apz/test/mochitest/test_bug1277814.html
Normal file
106
gfx/layers/apz/test/mochitest/test_bug1277814.html
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1277814
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1277814</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
function* test(testDriver) {
|
||||
// Trigger the buggy scenario
|
||||
var subframe = document.getElementById('bug1277814-div');
|
||||
subframe.classList.add('a');
|
||||
|
||||
// The transform change is animated, so let's step through 1s of animation
|
||||
var utils = SpecialPowers.getDOMWindowUtils(window);
|
||||
for (var i = 0; i < 60; i++) {
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
}
|
||||
utils.restoreNormalRefresh();
|
||||
|
||||
// Wait for the layer tree with any updated dispatch-to-content region to
|
||||
// get pushed over to the APZ
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
|
||||
// Trigger layerization of the subframe by scrolling the wheel over it
|
||||
yield moveMouseAndScrollWheelOver(subframe, 10, 10, testDriver);
|
||||
|
||||
// Give APZ the chance to compute a displayport, and content
|
||||
// to render based on it.
|
||||
yield waitForApzFlushedRepaints(testDriver);
|
||||
|
||||
// Examine the content-side APZ test data
|
||||
var contentTestData = utils.getContentAPZTestData();
|
||||
|
||||
// Test that the scroll frame for the div 'bug1277814-div' appears in
|
||||
// the APZ test data. The bug this test is for causes the displayport
|
||||
// calculation for this scroll frame to go wrong, causing it not to
|
||||
// become layerized.
|
||||
contentTestData = convertTestData(contentTestData);
|
||||
var foundIt = false;
|
||||
for (var seqNo in contentTestData.paints) {
|
||||
var paint = contentTestData.paints[seqNo];
|
||||
for (var scrollId in paint) {
|
||||
var scrollFrame = paint[scrollId];
|
||||
if ('contentDescription' in scrollFrame &&
|
||||
scrollFrame['contentDescription'].includes('bug1277814-div')) {
|
||||
foundIt = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
SimpleTest.ok(foundIt, "expected to find APZ test data for bug1277814-div");
|
||||
}
|
||||
|
||||
if (isApzEnabled()) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
pushPrefs([["apz.test.logging_enabled", true]])
|
||||
.then(waitUntilApzStable)
|
||||
.then(runContinuation(test))
|
||||
.then(SimpleTest.finish);
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
#bug1277814-div
|
||||
{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
padding: .5em;
|
||||
overflow: auto;
|
||||
color: white;
|
||||
background: green;
|
||||
max-width: 30em;
|
||||
max-height: 6em;
|
||||
visibility: hidden;
|
||||
transform: scaleY(0);
|
||||
transition: transform .15s ease-out, visibility 0s ease .15s;
|
||||
}
|
||||
#bug1277814-div.a
|
||||
{
|
||||
visibility: visible;
|
||||
transform: scaleY(1);
|
||||
transition: transform .15s ease-out;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Use a unique id because we'll be checking for it in the content
|
||||
description logged in the APZ test data -->
|
||||
<div id="bug1277814-div">
|
||||
CoolCmd<br>CoolCmd<br>CoolCmd<br>CoolCmd<br>
|
||||
CoolCmd<br>CoolCmd<br>CoolCmd<br>CoolCmd<br>
|
||||
CoolCmd<br>CoolCmd<br>CoolCmd<br>CoolCmd<br>
|
||||
CoolCmd<br>CoolCmd<br>CoolCmd<br>CoolCmd<br>
|
||||
CoolCmd<br>CoolCmd<br>CoolCmd<br>CoolCmd<br>
|
||||
<button>click me</button>
|
||||
</body>
|
||||
</html>
|
||||
131
gfx/layers/apz/test/mochitest/test_bug1304689-2.html
Normal file
131
gfx/layers/apz/test/mochitest/test_bug1304689-2.html
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1304689
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1285070</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style type="text/css">
|
||||
#outer {
|
||||
height: 400px;
|
||||
width: 415px;
|
||||
overflow: scroll;
|
||||
position: relative;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
#outer.contentBefore::before {
|
||||
top: 0;
|
||||
content: '';
|
||||
display: block;
|
||||
height: 2px;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
}
|
||||
</style>
|
||||
<script type="application/javascript">
|
||||
|
||||
function* test(testDriver) {
|
||||
var utils = SpecialPowers.DOMWindowUtils;
|
||||
var elm = document.getElementById('outer');
|
||||
|
||||
// Set margins on the element, to ensure it is layerized
|
||||
utils.setDisplayPortMarginsForElement(0, 0, 0, 0, elm, /*priority*/ 1);
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
|
||||
// Take control of the refresh driver
|
||||
utils.advanceTimeAndRefresh(0);
|
||||
|
||||
// Start a smooth-scroll animation in the compositor and let it go a few
|
||||
// frames, so that there is some "user scrolling" going on (per the comment
|
||||
// in AsyncPanZoomController::NotifyLayersUpdated)
|
||||
elm.scrollTop = 10;
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
|
||||
// Do another scroll update but also do a frame reconstruction within the same
|
||||
// tick of the refresh driver.
|
||||
elm.scrollTop = 100;
|
||||
elm.classList.add('contentBefore');
|
||||
|
||||
// Now let everything settle and all the animations run out
|
||||
for (var i = 0; i < 60; i++) {
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
}
|
||||
utils.restoreNormalRefresh();
|
||||
|
||||
yield flushApzRepaints(testDriver);
|
||||
is(elm.scrollTop, 100, "The scrollTop now should be y=100");
|
||||
}
|
||||
|
||||
if (isApzEnabled()) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
pushPrefs([["apz.displayport_expiry_ms", 0]])
|
||||
.then(waitUntilApzStable)
|
||||
.then(runContinuation(test))
|
||||
.then(SimpleTest.finish);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="outer">
|
||||
<div id="inner">
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
135
gfx/layers/apz/test/mochitest/test_bug1304689.html
Normal file
135
gfx/layers/apz/test/mochitest/test_bug1304689.html
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1304689
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1285070</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style type="text/css">
|
||||
#outer {
|
||||
height: 400px;
|
||||
width: 415px;
|
||||
overflow: scroll;
|
||||
position: relative;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
#outer.instant {
|
||||
scroll-behavior: auto;
|
||||
}
|
||||
#outer.contentBefore::before {
|
||||
top: 0;
|
||||
content: '';
|
||||
display: block;
|
||||
height: 2px;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
}
|
||||
</style>
|
||||
<script type="application/javascript">
|
||||
|
||||
function* test(testDriver) {
|
||||
var utils = SpecialPowers.DOMWindowUtils;
|
||||
var elm = document.getElementById('outer');
|
||||
|
||||
// Set margins on the element, to ensure it is layerized
|
||||
utils.setDisplayPortMarginsForElement(0, 0, 0, 0, elm, /*priority*/ 1);
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
|
||||
// Take control of the refresh driver
|
||||
utils.advanceTimeAndRefresh(0);
|
||||
|
||||
// Start a smooth-scroll animation in the compositor and let it go a few
|
||||
// frames, so that there is some "user scrolling" going on (per the comment
|
||||
// in AsyncPanZoomController::NotifyLayersUpdated)
|
||||
elm.scrollTop = 10;
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
|
||||
// Do another scroll update but also do a frame reconstruction within the same
|
||||
// tick of the refresh driver.
|
||||
elm.classList.add('instant');
|
||||
elm.scrollTop = 100;
|
||||
elm.classList.add('contentBefore');
|
||||
|
||||
// Now let everything settle and all the animations run out
|
||||
for (var i = 0; i < 60; i++) {
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
}
|
||||
utils.restoreNormalRefresh();
|
||||
|
||||
yield flushApzRepaints(testDriver);
|
||||
is(elm.scrollTop, 100, "The scrollTop now should be y=100");
|
||||
}
|
||||
|
||||
if (isApzEnabled()) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
pushPrefs([["apz.displayport_expiry_ms", 0]])
|
||||
.then(waitUntilApzStable)
|
||||
.then(runContinuation(test))
|
||||
.then(SimpleTest.finish);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="outer">
|
||||
<div id="inner">
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
this is some scrollable text.<br>
|
||||
this is a second line to make the scrolling more obvious.<br>
|
||||
and a third for good measure.<br>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
38
gfx/layers/apz/test/mochitest/test_bug982141.html
Normal file
38
gfx/layers/apz/test/mochitest/test_bug982141.html
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=982141
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 982141</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
if (isApzEnabled()) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Run the actual test in its own window, because it requires that the
|
||||
// root APZC not be scrollable. Mochitest pages themselves often run
|
||||
// inside an iframe which means we have no control over the root APZC.
|
||||
var w = null;
|
||||
window.onload = function() {
|
||||
pushPrefs([["apz.test.logging_enabled", true]]).then(function() {
|
||||
w = window.open("helper_bug982141.html", "_blank");
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function finishTest() {
|
||||
w.close();
|
||||
SimpleTest.finish();
|
||||
};
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=982141">Mozilla Bug 982141</a>
|
||||
</body>
|
||||
</html>
|
||||
218
gfx/layers/apz/test/mochitest/test_frame_reconstruction.html
Normal file
218
gfx/layers/apz/test/mochitest/test_frame_reconstruction.html
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1235899
|
||||
-->
|
||||
<head>
|
||||
<title>Test for bug 1235899</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
.outer {
|
||||
height: 400px;
|
||||
width: 415px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.inner {
|
||||
height: 100%;
|
||||
outline: none;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
position: relative;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
.outer.contentBefore::before {
|
||||
top: 0;
|
||||
content: '';
|
||||
display: block;
|
||||
height: 2px;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1235899">Mozilla Bug 1235899</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<p>You should be able to fling this list without it stopping abruptly</p>
|
||||
<div class="outer">
|
||||
<div class="inner">
|
||||
<ol>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
function* test(testDriver) {
|
||||
var elm = document.getElementsByClassName('inner')[0];
|
||||
elm.scrollTop = 0;
|
||||
yield flushApzRepaints(testDriver);
|
||||
|
||||
// Take over control of the refresh driver and compositor
|
||||
var utils = SpecialPowers.DOMWindowUtils;
|
||||
utils.advanceTimeAndRefresh(0);
|
||||
|
||||
// Kick off an APZ smooth-scroll to 0,200
|
||||
elm.scrollTo(0, 200);
|
||||
yield waitForAllPaints(function() { setTimeout(testDriver, 0); });
|
||||
|
||||
// Let's do a couple of frames of the animation, and make sure it's going
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
yield flushApzRepaints(testDriver);
|
||||
ok(elm.scrollTop > 0, "APZ animation in progress", "scrollTop is now " + elm.scrollTop);
|
||||
ok(elm.scrollTop < 200, "APZ animation not yet completed", "scrollTop is now " + elm.scrollTop);
|
||||
|
||||
var frameReconstructionTriggered = 0;
|
||||
// Register the listener that triggers the frame reconstruction
|
||||
elm.onscroll = function() {
|
||||
// Do the reconstruction
|
||||
elm.parentNode.classList.add('contentBefore');
|
||||
frameReconstructionTriggered++;
|
||||
// schedule a thing to undo the changes above
|
||||
setTimeout(function() {
|
||||
elm.parentNode.classList.remove('contentBefore');
|
||||
}, 0);
|
||||
}
|
||||
|
||||
// and do a few more frames of the animation, this should trigger the listener
|
||||
// and the frame reconstruction
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
yield flushApzRepaints(testDriver);
|
||||
ok(elm.scrollTop < 200, "APZ animation not yet completed", "scrollTop is now " + elm.scrollTop);
|
||||
ok(frameReconstructionTriggered > 0, "Frame reconstruction triggered", "reconstruction triggered " + frameReconstructionTriggered + " times");
|
||||
|
||||
// and now run to completion
|
||||
for (var i = 0; i < 100; i++) {
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
}
|
||||
utils.restoreNormalRefresh();
|
||||
yield waitForAllPaints(function() { setTimeout(testDriver, 0); });
|
||||
yield flushApzRepaints(testDriver);
|
||||
|
||||
is(elm.scrollTop, 200, "Element should have scrolled by 200px");
|
||||
}
|
||||
|
||||
if (isApzEnabled()) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.expectAssertions(0, 1); // this test triggers an assertion, see bug 1247050
|
||||
waitUntilApzStable()
|
||||
.then(runContinuation(test))
|
||||
.then(SimpleTest.finish);
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
35
gfx/layers/apz/test/mochitest/test_group_mouseevents.html
Normal file
35
gfx/layers/apz/test/mochitest/test_group_mouseevents.html
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Various mouse tests that spawn in new windows</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
var subtests = [
|
||||
// Sanity test to synthesize a mouse click
|
||||
{'file': 'helper_click.html?dtc=false'},
|
||||
// Same as above, but with a dispatch-to-content region that exercises the
|
||||
// main-thread notification codepaths for mouse events
|
||||
{'file': 'helper_click.html?dtc=true'},
|
||||
// Sanity test for click but with some mouse movement between the down and up
|
||||
{'file': 'helper_drag_click.html'},
|
||||
// Test for dragging on a fake-scrollbar element that scrolls the page
|
||||
{'file': 'helper_drag_scroll.html'}
|
||||
];
|
||||
|
||||
if (isApzEnabled()) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
window.onload = function() {
|
||||
runSubtestsSeriallyInFreshWindows(subtests)
|
||||
.then(SimpleTest.finish);
|
||||
};
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
31
gfx/layers/apz/test/mochitest/test_group_pointerevents.html
Normal file
31
gfx/layers/apz/test/mochitest/test_group_pointerevents.html
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1285070
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1285070</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
var subtests = [
|
||||
{'file': 'helper_bug1285070.html', 'prefs': [["dom.w3c_pointer_events.enabled", true]]},
|
||||
{'file': 'helper_bug1299195.html', 'prefs': [["dom.w3c_pointer_events.enabled", true]]}
|
||||
];
|
||||
|
||||
if (isApzEnabled()) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
window.onload = function() {
|
||||
runSubtestsSeriallyInFreshWindows(subtests)
|
||||
.then(SimpleTest.finish);
|
||||
};
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
104
gfx/layers/apz/test/mochitest/test_group_touchevents.html
Normal file
104
gfx/layers/apz/test/mochitest/test_group_touchevents.html
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Various touch tests that spawn in new windows</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
var basic_pan_prefs = [
|
||||
// Dropping the touch slop to 0 makes the tests easier to write because
|
||||
// we can just do a one-pixel drag to get over the pan threshold rather
|
||||
// than having to hard-code some larger value.
|
||||
["apz.touch_start_tolerance", "0.0"],
|
||||
// The touchstart from the drag can turn into a long-tap if the touch-move
|
||||
// events get held up. Try to prevent that by making long-taps require
|
||||
// a 10 second hold. Note that we also cannot enable chaos mode on this
|
||||
// test for this reason, since chaos mode can cause the long-press timer
|
||||
// to fire sooner than the pref dictates.
|
||||
["ui.click_hold_context_menus.delay", 10000],
|
||||
// The subtests in this test do touch-drags to pan the page, but we don't
|
||||
// want those pans to turn into fling animations, so we increase the
|
||||
// fling min velocity requirement absurdly high.
|
||||
["apz.fling_min_velocity_threshold", "10000"],
|
||||
// The helper_div_pan's div gets a displayport on scroll, but if the
|
||||
// test takes too long the displayport can expire before the new scroll
|
||||
// position is synced back to the main thread. So we disable displayport
|
||||
// expiry for these tests.
|
||||
["apz.displayport_expiry_ms", 0],
|
||||
];
|
||||
|
||||
var touch_action_prefs = basic_pan_prefs.slice(); // make a copy
|
||||
touch_action_prefs.push(["layout.css.touch_action.enabled", true]);
|
||||
|
||||
var isWindows = (getPlatform() == "windows");
|
||||
|
||||
var subtests = [
|
||||
// Simple tests to exercise basic panning behaviour
|
||||
{'file': 'helper_basic_pan.html', 'prefs': basic_pan_prefs},
|
||||
{'file': 'helper_div_pan.html', 'prefs': basic_pan_prefs},
|
||||
{'file': 'helper_iframe_pan.html', 'prefs': basic_pan_prefs},
|
||||
|
||||
// Simple test to exercise touch-tapping behaviour
|
||||
{'file': 'helper_tap.html'},
|
||||
// Tapping, but with a full-zoom applied
|
||||
{'file': 'helper_tap_fullzoom.html'},
|
||||
|
||||
// For the following two tests, disable displayport suppression to make sure it
|
||||
// doesn't interfere with the test by scheduling paints non-deterministically.
|
||||
{'file': 'helper_scrollto_tap.html?true', 'prefs': [["apz.paint_skipping.enabled", true]], 'dp_suppression': false},
|
||||
{'file': 'helper_scrollto_tap.html?false', 'prefs': [["apz.paint_skipping.enabled", false]], 'dp_suppression': false},
|
||||
|
||||
// Taps on media elements to make sure the touchend event is delivered
|
||||
// properly. We increase the long-tap timeout to ensure it doesn't get trip
|
||||
// during the tap.
|
||||
// Also this test (on Windows) cannot satisfy the OS requirement of providing
|
||||
// an injected touch event every 100ms, because it waits for a paint between
|
||||
// the touchstart and the touchend, so we have to use the "fake injection"
|
||||
// code instead.
|
||||
{'file': 'helper_bug1162771.html', 'prefs': [["ui.click_hold_context_menus.delay", 10000],
|
||||
["apz.test.fails_with_native_injection", isWindows]]},
|
||||
|
||||
// As with the previous test, this test cannot inject touch events every 100ms
|
||||
// because it waits for a long-tap, so we have to use the "fake injection" code
|
||||
// instead.
|
||||
{'file': 'helper_long_tap.html', 'prefs': [["apz.test.fails_with_native_injection", isWindows]]},
|
||||
|
||||
// For the following test, we want to make sure APZ doesn't wait for a content
|
||||
// response that is never going to arrive. To detect this we set the content response
|
||||
// timeout to a day, so that the entire test times out and fails if APZ does
|
||||
// end up waiting.
|
||||
{'file': 'helper_tap_passive.html', 'prefs': [["apz.content_response_timeout", 24 * 60 * 60 * 1000],
|
||||
["apz.test.fails_with_native_injection", isWindows]]},
|
||||
|
||||
// Simple test to exercise touch-action CSS property
|
||||
{'file': 'helper_touch_action.html', 'prefs': touch_action_prefs},
|
||||
// More complex touch-action tests, with overlapping regions and such
|
||||
{'file': 'helper_touch_action_complex.html', 'prefs': touch_action_prefs},
|
||||
// Tests that touch-action CSS properties are handled in APZ without waiting
|
||||
// on the main-thread, when possible
|
||||
{'file': 'helper_touch_action_regions.html', 'prefs': touch_action_prefs},
|
||||
];
|
||||
|
||||
if (isApzEnabled()) {
|
||||
ok(window.TouchEvent, "Check if TouchEvent is supported (it should be, the test harness forces it on everywhere)");
|
||||
if (getPlatform() == "android") {
|
||||
// This has a lot of subtests, and Android emulators are slow.
|
||||
SimpleTest.requestLongerTimeout(2);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
window.onload = function() {
|
||||
runSubtestsSeriallyInFreshWindows(subtests)
|
||||
.then(SimpleTest.finish);
|
||||
};
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
41
gfx/layers/apz/test/mochitest/test_group_wheelevents.html
Normal file
41
gfx/layers/apz/test/mochitest/test_group_wheelevents.html
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Various wheel-scrolling tests that spawn in new windows</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
var prefs = [
|
||||
// turn off smooth scrolling so that we don't have to wait for
|
||||
// APZ animations to finish before sampling the scroll offset
|
||||
['general.smoothScroll', false],
|
||||
// ensure that any mouse movement will trigger a new wheel transaction,
|
||||
// because in this test we move the mouse a bunch and want to recalculate
|
||||
// the target APZC after each such movement.
|
||||
['mousewheel.transaction.ignoremovedelay', 0],
|
||||
['mousewheel.transaction.timeout', 0]
|
||||
]
|
||||
|
||||
var subtests = [
|
||||
{'file': 'helper_scroll_on_position_fixed.html', 'prefs': prefs},
|
||||
{'file': 'helper_bug1271432.html', 'prefs': prefs},
|
||||
{'file': 'helper_scroll_inactive_perspective.html', 'prefs': prefs},
|
||||
{'file': 'helper_scroll_inactive_zindex.html', 'prefs': prefs}
|
||||
];
|
||||
|
||||
if (isApzEnabled()) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
window.onload = function() {
|
||||
runSubtestsSeriallyInFreshWindows(subtests)
|
||||
.then(SimpleTest.finish);
|
||||
};
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
44
gfx/layers/apz/test/mochitest/test_group_zoom.html
Normal file
44
gfx/layers/apz/test/mochitest/test_group_zoom.html
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Various zoom-related tests that spawn in new windows</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
var prefs = [
|
||||
// We need the APZ paint logging information
|
||||
["apz.test.logging_enabled", true],
|
||||
// Dropping the touch slop to 0 makes the tests easier to write because
|
||||
// we can just do a one-pixel drag to get over the pan threshold rather
|
||||
// than having to hard-code some larger value.
|
||||
["apz.touch_start_tolerance", "0.0"],
|
||||
// The subtests in this test do touch-drags to pan the page, but we don't
|
||||
// want those pans to turn into fling animations, so we increase the
|
||||
// fling-stop threshold velocity to absurdly high.
|
||||
["apz.fling_stopped_threshold", "10000"],
|
||||
// The helper_bug1280013's div gets a displayport on scroll, but if the
|
||||
// test takes too long the displayport can expire before we read the value
|
||||
// out of the test. So we disable displayport expiry for these tests.
|
||||
["apz.displayport_expiry_ms", 0],
|
||||
];
|
||||
|
||||
var subtests = [
|
||||
{'file': 'helper_bug1280013.html', 'prefs': prefs},
|
||||
];
|
||||
|
||||
if (isApzEnabled()) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
window.onload = function() {
|
||||
runSubtestsSeriallyInFreshWindows(subtests)
|
||||
.then(SimpleTest.finish);
|
||||
};
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
719
gfx/layers/apz/test/mochitest/test_interrupted_reflow.html
Normal file
719
gfx/layers/apz/test/mochitest/test_interrupted_reflow.html
Normal file
|
|
@ -0,0 +1,719 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1292781
|
||||
-->
|
||||
<head>
|
||||
<title>Test for bug 1292781</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
.outer {
|
||||
height: 400px;
|
||||
width: 415px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.inner {
|
||||
height: 100%;
|
||||
outline: none;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
position: relative;
|
||||
}
|
||||
.inner div:nth-child(even) {
|
||||
background-color: lightblue;
|
||||
}
|
||||
.inner div:nth-child(odd) {
|
||||
background-color: lightgreen;
|
||||
}
|
||||
.outer.contentBefore::before {
|
||||
top: 0;
|
||||
content: '';
|
||||
display: block;
|
||||
height: 2px;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1292781">Mozilla Bug 1292781</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<p>The frame reconstruction should not leave this scrollframe in a bad state</p>
|
||||
<div class="outer">
|
||||
<div class="inner">
|
||||
this is the top of the scrollframe.
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
this is near the top of the scrollframe.
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
this is near the bottom of the scrollframe.
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
<div>this is a box</div>
|
||||
this is the bottom of the scrollframe.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script type="text/javascript">
|
||||
|
||||
// Returns a list of async scroll offsets that the |inner| element had, one for
|
||||
// each paint.
|
||||
function getAsyncScrollOffsets(aPaintsToIgnore) {
|
||||
var offsets = [];
|
||||
var compositorTestData = SpecialPowers.getDOMWindowUtils(window).getCompositorAPZTestData();
|
||||
var buckets = compositorTestData.paints.slice(aPaintsToIgnore);
|
||||
ok(buckets.length >= 3, "Expected at least three paints in the compositor test data");
|
||||
var childIsLayerized = false;
|
||||
for (var i = 0; i < buckets.length; ++i) {
|
||||
var apzcTree = buildApzcTree(convertScrollFrameData(buckets[i].scrollFrames));
|
||||
var rcd = findRcdNode(apzcTree);
|
||||
if (rcd == null) {
|
||||
continue;
|
||||
}
|
||||
if (rcd.children.length > 0) {
|
||||
// The child may not be layerized in the first few paints, but once it is
|
||||
// layerized, it should stay layerized.
|
||||
childIsLayerized = true;
|
||||
}
|
||||
if (!childIsLayerized) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ok(rcd.children.length == 1, "Root content APZC has exactly one child");
|
||||
var scroll = rcd.children[0].asyncScrollOffset;
|
||||
var pieces = scroll.replace(/[()\s]+/g, '').split(',');
|
||||
is(pieces.length, 2, "expected string of form (x,y)");
|
||||
offsets.push({ x: parseInt(pieces[0]),
|
||||
y: parseInt(pieces[1]) });
|
||||
}
|
||||
return offsets;
|
||||
}
|
||||
|
||||
function* test(testDriver) {
|
||||
var utils = SpecialPowers.DOMWindowUtils;
|
||||
|
||||
// The APZ test data accumulates whenever a test turns it on. We just want
|
||||
// the data for this test, so we check how many frames are already recorded
|
||||
// and discard those later.
|
||||
var framesToSkip = SpecialPowers.getDOMWindowUtils(window).getCompositorAPZTestData().paints.length;
|
||||
|
||||
var elm = document.getElementsByClassName('inner')[0];
|
||||
// Set a zero-margin displayport to ensure that the element is async-scrollable
|
||||
// otherwise on Fennec it is not
|
||||
utils.setDisplayPortMarginsForElement(0, 0, 0, 0, elm, 0);
|
||||
|
||||
var maxScroll = elm.scrollTopMax;
|
||||
elm.scrollTop = maxScroll;
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
|
||||
// Take control of the refresh driver
|
||||
utils.advanceTimeAndRefresh(0);
|
||||
|
||||
// Force the next reflow to get interrupted
|
||||
utils.forceReflowInterrupt();
|
||||
|
||||
// Make a change that triggers frame reconstruction, and then tick the refresh
|
||||
// driver so that layout processes the pending restyles and then runs an
|
||||
// interruptible reflow. That reflow *will* be interrupted (because of the flag
|
||||
// we set above), and we should end up with a transient 0,0 scroll offset
|
||||
// being sent to the compositor.
|
||||
elm.parentNode.classList.add('contentBefore');
|
||||
utils.advanceTimeAndRefresh(0);
|
||||
// On android, and maybe non-e10s platforms generally, we need to manually
|
||||
// kick the paint to send the layer transaction to the compositor.
|
||||
yield waitForAllPaints(function() { setTimeout(testDriver, 0) });
|
||||
|
||||
// Read the main-thread scroll offset; although this is temporarily 0,0 that
|
||||
// temporary value is never exposed to content - instead reading this value
|
||||
// will finish doing the interrupted reflow from above and then report the
|
||||
// correct scroll offset.
|
||||
is(elm.scrollTop, maxScroll, "Main-thread scroll position was restored");
|
||||
|
||||
// .. and now flush everything to make sure the state gets pushed over to the
|
||||
// compositor and APZ as well.
|
||||
utils.restoreNormalRefresh();
|
||||
yield waitForApzFlushedRepaints(testDriver);
|
||||
|
||||
// Now we pull the compositor data and check it. What we expect to see is that
|
||||
// the scroll position goes to maxScroll, then drops to 0 and then goes back
|
||||
// to maxScroll. This test is specifically testing that last bit - that it
|
||||
// properly gets restored from 0 to maxScroll.
|
||||
// The one hitch is that on Android this page is loaded with some amount of
|
||||
// zoom, and the async scroll is in ParentLayerPixel coordinates, so it will
|
||||
// not match maxScroll exactly. Since we can't reliably compute what that
|
||||
// ParentLayer scroll will be, we just make sure the async scroll is nonzero
|
||||
// and use the first value we encounter to verify that it got restored properly.
|
||||
// The other alternative is to spawn this test into a new window with 1.0 zoom
|
||||
// but I'm tired of doing that for pretty much every test.
|
||||
var state = 0;
|
||||
var asyncScrollOffsets = getAsyncScrollOffsets(framesToSkip);
|
||||
dump("Got scroll offsets: " + JSON.stringify(asyncScrollOffsets) + "\n");
|
||||
var maxScrollParentLayerPixels = maxScroll;
|
||||
while (asyncScrollOffsets.length > 0) {
|
||||
let offset = asyncScrollOffsets.shift();
|
||||
switch (state) {
|
||||
// 0 is the initial state, the scroll offset might be zero but should
|
||||
// become non-zero from when we set scrollTop to scrollTopMax
|
||||
case 0:
|
||||
if (offset.y == 0) {
|
||||
break;
|
||||
}
|
||||
if (getPlatform() == "android") {
|
||||
ok(offset.y > 0, "Async scroll y of scrollframe is " + offset.y);
|
||||
maxScrollParentLayerPixels = offset.y;
|
||||
} else {
|
||||
is(offset.y, maxScrollParentLayerPixels, "Async scroll y of scrollframe is " + offset.y);
|
||||
}
|
||||
state = 1;
|
||||
break;
|
||||
|
||||
// state 1 starts out at maxScrollParentLayerPixels, should drop to 0
|
||||
// because of the interrupted reflow putting the scroll into a transient
|
||||
// zero state
|
||||
case 1:
|
||||
if (offset.y == maxScrollParentLayerPixels) {
|
||||
break;
|
||||
}
|
||||
is(offset.y, 0, "Async scroll position was temporarily 0");
|
||||
state = 2;
|
||||
break;
|
||||
|
||||
// state 2 starts out the transient 0 scroll offset, and we expect the
|
||||
// scroll position to get restored back to maxScrollParentLayerPixels
|
||||
case 2:
|
||||
if (offset.y == 0) {
|
||||
break;
|
||||
}
|
||||
is(offset.y, maxScrollParentLayerPixels, "Async scroll y of scrollframe restored to " + offset.y);
|
||||
state = 3;
|
||||
break;
|
||||
|
||||
// Terminal state. The scroll position should stay at maxScrollParentLayerPixels
|
||||
case 3:
|
||||
is(offset.y, maxScrollParentLayerPixels, "Scroll position maintained");
|
||||
break;
|
||||
}
|
||||
}
|
||||
is(state, 3, "The scroll position did drop to 0 and then get restored properly");
|
||||
}
|
||||
|
||||
if (isApzEnabled()) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
pushPrefs([["apz.test.logging_enabled", true],
|
||||
["apz.displayport_expiry_ms", 0]])
|
||||
.then(waitUntilApzStable)
|
||||
.then(runContinuation(test))
|
||||
.then(SimpleTest.finish);
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
214
gfx/layers/apz/test/mochitest/test_layerization.html
Normal file
214
gfx/layers/apz/test/mochitest/test_layerization.html
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1173580
|
||||
-->
|
||||
<head>
|
||||
<title>Test for layerization</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="helper_subframe_style.css"/>
|
||||
<style>
|
||||
#container {
|
||||
display: flex;
|
||||
overflow: scroll;
|
||||
height: 500px;
|
||||
}
|
||||
.outer-frame {
|
||||
height: 500px;
|
||||
overflow: scroll;
|
||||
flex-basis: 100%;
|
||||
background: repeating-linear-gradient(#CCC, #CCC 100px, #BBB 100px, #BBB 200px);
|
||||
}
|
||||
#container-content {
|
||||
height: 200%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1173580">APZ layerization tests</a>
|
||||
<p id="display"></p>
|
||||
<div id="container">
|
||||
<div id="outer1" class="outer-frame">
|
||||
<div id="inner1" class="inner-frame">
|
||||
<div class="inner-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="outer2" class="outer-frame">
|
||||
<div id="inner2" class="inner-frame">
|
||||
<div class="inner-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
<iframe id="outer3" class="outer-frame" src="helper_iframe1.html"></iframe>
|
||||
<iframe id="outer4" class="outer-frame" src="helper_iframe2.html"></iframe>
|
||||
<!-- The container-content div ensures 'container' is scrollable, so the
|
||||
optimization that layerizes the primary async-scrollable frame on page
|
||||
load layerizes it rather than its child subframes. -->
|
||||
<div id="container-content"></div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
// Scroll the mouse wheel over |element|.
|
||||
function scrollWheelOver(element, waitForScroll, testDriver) {
|
||||
moveMouseAndScrollWheelOver(element, 10, 10, testDriver, waitForScroll);
|
||||
}
|
||||
|
||||
const DISPLAYPORT_EXPIRY = 100;
|
||||
|
||||
// This helper function produces another helper function, which, when invoked,
|
||||
// invokes the provided testDriver argument in a setTimeout 0. This is really
|
||||
// just useful in cases when there are no paints pending, because then
|
||||
// waitForAllPaints will invoke its callback synchronously. If we did
|
||||
// waitForAllPaints(testDriver) that might cause reentrancy into the testDriver
|
||||
// which is bad. This function works around that.
|
||||
function asyncWrapper(testDriver) {
|
||||
return function() {
|
||||
setTimeout(testDriver, 0);
|
||||
};
|
||||
}
|
||||
|
||||
function* test(testDriver) {
|
||||
// Initially, nothing should be layerized.
|
||||
ok(!isLayerized('outer1'), "initially 'outer1' should not be layerized");
|
||||
ok(!isLayerized('inner1'), "initially 'inner1' should not be layerized");
|
||||
ok(!isLayerized('outer2'), "initially 'outer2' should not be layerized");
|
||||
ok(!isLayerized('inner2'), "initially 'inner2' should not be layerized");
|
||||
ok(!isLayerized('outer3'), "initially 'outer3' should not be layerized");
|
||||
ok(!isLayerized('inner3'), "initially 'inner3' should not be layerized");
|
||||
ok(!isLayerized('outer4'), "initially 'outer4' should not be layerized");
|
||||
ok(!isLayerized('inner4'), "initially 'inner4' should not be layerized");
|
||||
|
||||
// Scrolling over outer1 should layerize outer1, but not inner1.
|
||||
yield scrollWheelOver(document.getElementById('outer1'), true, testDriver);
|
||||
ok(isLayerized('outer1'), "scrolling 'outer1' should cause it to be layerized");
|
||||
ok(!isLayerized('inner1'), "scrolling 'outer1' should not cause 'inner1' to be layerized");
|
||||
|
||||
// Scrolling over inner2 should layerize both outer2 and inner2.
|
||||
yield scrollWheelOver(document.getElementById('inner2'), true, testDriver);
|
||||
ok(isLayerized('inner2'), "scrolling 'inner2' should cause it to be layerized");
|
||||
ok(isLayerized('outer2'), "scrolling 'inner2' should also cause 'outer2' to be layerized");
|
||||
|
||||
// The second half of the test repeats the same checks as the first half,
|
||||
// but with an iframe as the outer scrollable frame.
|
||||
|
||||
// Scrolling over outer3 should layerize outer3, but not inner3.
|
||||
yield scrollWheelOver(document.getElementById('outer3').contentDocument.documentElement, true, testDriver);
|
||||
ok(isLayerized('outer3'), "scrolling 'outer3' should cause it to be layerized");
|
||||
ok(!isLayerized('inner3'), "scrolling 'outer3' should not cause 'inner3' to be layerized");
|
||||
|
||||
// Scrolling over outer4 should layerize both outer4 and inner4.
|
||||
yield scrollWheelOver(document.getElementById('outer4').contentDocument.getElementById('inner4'), true, testDriver);
|
||||
ok(isLayerized('inner4'), "scrolling 'inner4' should cause it to be layerized");
|
||||
ok(isLayerized('outer4'), "scrolling 'inner4' should also cause 'outer4' to be layerized");
|
||||
|
||||
// Now we enable displayport expiry, and verify that things are still
|
||||
// layerized as they were before.
|
||||
yield SpecialPowers.pushPrefEnv({"set": [["apz.displayport_expiry_ms", DISPLAYPORT_EXPIRY]]}, testDriver);
|
||||
ok(isLayerized('outer1'), "outer1 is still layerized after enabling expiry");
|
||||
ok(!isLayerized('inner1'), "inner1 is still not layerized after enabling expiry");
|
||||
ok(isLayerized('outer2'), "outer2 is still layerized after enabling expiry");
|
||||
ok(isLayerized('inner2'), "inner2 is still layerized after enabling expiry");
|
||||
ok(isLayerized('outer3'), "outer3 is still layerized after enabling expiry");
|
||||
ok(!isLayerized('inner3'), "inner3 is still not layerized after enabling expiry");
|
||||
ok(isLayerized('outer4'), "outer4 is still layerized after enabling expiry");
|
||||
ok(isLayerized('inner4'), "inner4 is still layerized after enabling expiry");
|
||||
|
||||
// Now we trigger a scroll on some of the things still layerized, so that
|
||||
// the displayport expiry gets triggered.
|
||||
|
||||
// Expire displayport with scrolling on outer1
|
||||
yield scrollWheelOver(document.getElementById('outer1'), true, testDriver);
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
yield setTimeout(testDriver, DISPLAYPORT_EXPIRY);
|
||||
yield waitForAllPaints(asyncWrapper(testDriver));
|
||||
ok(!isLayerized('outer1'), "outer1 is no longer layerized after displayport expiry");
|
||||
ok(!isLayerized('inner1'), "inner1 is still not layerized after displayport expiry");
|
||||
|
||||
// Expire displayport with scrolling on inner2
|
||||
yield scrollWheelOver(document.getElementById('inner2'), true, testDriver);
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
// Once the expiry elapses, it will trigger expiry on outer2, so we check
|
||||
// both, one at a time.
|
||||
yield setTimeout(testDriver, DISPLAYPORT_EXPIRY);
|
||||
yield waitForAllPaints(asyncWrapper(testDriver));
|
||||
ok(!isLayerized('inner2'), "inner2 is no longer layerized after displayport expiry");
|
||||
yield setTimeout(testDriver, DISPLAYPORT_EXPIRY);
|
||||
yield waitForAllPaints(asyncWrapper(testDriver));
|
||||
ok(!isLayerized('outer2'), "outer2 got de-layerized with inner2");
|
||||
|
||||
// Scroll on inner3. inner3 isn't layerized, and this will cause it to
|
||||
// get layerized, but it will also trigger displayport expiration for inner3
|
||||
// which will eventually trigger displayport expiration on inner3 and outer3.
|
||||
// Note that the displayport expiration might actually happen before the wheel
|
||||
// input is processed in the compositor (see bug 1246480 comment 3), and so
|
||||
// we make sure not to wait for a scroll event here, since it may never fire.
|
||||
// However, if we do get a scroll event while waiting for the expiry, we need
|
||||
// to restart the expiry timer because the displayport expiry got reset. There's
|
||||
// no good way that I can think of to deterministically avoid doing this.
|
||||
let inner3 = document.getElementById('outer3').contentDocument.getElementById('inner3');
|
||||
yield scrollWheelOver(inner3, false, testDriver);
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
var timerId = setTimeout(testDriver, DISPLAYPORT_EXPIRY);
|
||||
var timeoutResetter = function() {
|
||||
ok(true, "Got a scroll event; resetting timer...");
|
||||
clearTimeout(timerId);
|
||||
setTimeout(testDriver, DISPLAYPORT_EXPIRY);
|
||||
// by not updating timerId we ensure that this listener resets the timeout
|
||||
// at most once.
|
||||
};
|
||||
inner3.addEventListener('scroll', timeoutResetter, false);
|
||||
yield; // wait for the setTimeout to elapse
|
||||
inner3.removeEventListener('scroll', timeoutResetter, false);
|
||||
|
||||
yield waitForAllPaints(asyncWrapper(testDriver));
|
||||
ok(!isLayerized('inner3'), "inner3 becomes unlayerized after expiry");
|
||||
yield setTimeout(testDriver, DISPLAYPORT_EXPIRY);
|
||||
yield waitForAllPaints(asyncWrapper(testDriver));
|
||||
ok(!isLayerized('outer3'), "outer3 is no longer layerized after inner3 triggered expiry");
|
||||
|
||||
// Scroll outer4 and wait for the expiry. It should NOT get expired because
|
||||
// inner4 is still layerized
|
||||
yield scrollWheelOver(document.getElementById('outer4').contentDocument.documentElement, true, testDriver);
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
// Wait for the expiry to elapse
|
||||
yield setTimeout(testDriver, DISPLAYPORT_EXPIRY);
|
||||
yield waitForAllPaints(asyncWrapper(testDriver));
|
||||
ok(isLayerized('inner4'), "inner4 is still layerized because it never expired");
|
||||
ok(isLayerized('outer4'), "outer4 is still layerized because inner4 is still layerized");
|
||||
}
|
||||
|
||||
if (isApzEnabled()) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.requestFlakyTimeout("we are testing code that measures an actual timeout");
|
||||
SimpleTest.expectAssertions(0, 8); // we get a bunch of "ASSERTION: Bounds computation mismatch" sometimes (bug 1232856)
|
||||
|
||||
// Disable smooth scrolling, because it results in long-running scroll
|
||||
// animations that can result in a 'scroll' event triggered by an earlier
|
||||
// wheel event as corresponding to a later wheel event.
|
||||
// Also enable APZ test logging, since we use that data to determine whether
|
||||
// a scroll frame was layerized.
|
||||
pushPrefs([["general.smoothScroll", false],
|
||||
["apz.displayport_expiry_ms", 0],
|
||||
["apz.test.logging_enabled", true]])
|
||||
.then(waitUntilApzStable)
|
||||
.then(runContinuation(test))
|
||||
.then(SimpleTest.finish);
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,541 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test scrolling flattened inactive frames</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<style>
|
||||
p {
|
||||
width:200px;
|
||||
height:200px;
|
||||
border:solid 1px black;
|
||||
overflow:auto;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="iframe-body" style="overflow: auto; height: 1000px">
|
||||
<hr>
|
||||
<hr>
|
||||
<hr>
|
||||
<p>
|
||||
1 <br>
|
||||
2 <br>
|
||||
3 <br>
|
||||
4 <br>
|
||||
5 <br>
|
||||
6 <br>
|
||||
7 <br>
|
||||
8 <br>
|
||||
9 <br>
|
||||
10 <br>
|
||||
11 <br>
|
||||
12 <br>
|
||||
13 <br>
|
||||
14 <br>
|
||||
15 <br>
|
||||
16 <br>
|
||||
17 <br>
|
||||
18 <br>
|
||||
19 <br>
|
||||
20 <br>
|
||||
21 <br>
|
||||
22 <br>
|
||||
23 <br>
|
||||
24 <br>
|
||||
25 <br>
|
||||
26 <br>
|
||||
27 <br>
|
||||
28 <br>
|
||||
29 <br>
|
||||
30 <br>
|
||||
31 <br>
|
||||
32 <br>
|
||||
33 <br>
|
||||
34 <br>
|
||||
35 <br>
|
||||
36 <br>
|
||||
37 <br>
|
||||
38 <br>
|
||||
39 <br>
|
||||
40 <br>
|
||||
|
||||
</p><p id="subframe">
|
||||
1 <br>
|
||||
2 <br>
|
||||
3 <br>
|
||||
4 <br>
|
||||
5 <br>
|
||||
6 <br>
|
||||
7 <br>
|
||||
8 <br>
|
||||
9 <br>
|
||||
10 <br>
|
||||
11 <br>
|
||||
12 <br>
|
||||
13 <br>
|
||||
14 <br>
|
||||
15 <br>
|
||||
16 <br>
|
||||
17 <br>
|
||||
18 <br>
|
||||
19 <br>
|
||||
20 <br>
|
||||
21 <br>
|
||||
22 <br>
|
||||
23 <br>
|
||||
24 <br>
|
||||
25 <br>
|
||||
26 <br>
|
||||
27 <br>
|
||||
28 <br>
|
||||
29 <br>
|
||||
30 <br>
|
||||
31 <br>
|
||||
32 <br>
|
||||
33 <br>
|
||||
34 <br>
|
||||
35 <br>
|
||||
36 <br>
|
||||
37 <br>
|
||||
38 <br>
|
||||
39 <br>
|
||||
40 <br>
|
||||
|
||||
</p><p>
|
||||
1 <br>
|
||||
2 <br>
|
||||
3 <br>
|
||||
4 <br>
|
||||
5 <br>
|
||||
6 <br>
|
||||
7 <br>
|
||||
8 <br>
|
||||
9 <br>
|
||||
10 <br>
|
||||
11 <br>
|
||||
12 <br>
|
||||
13 <br>
|
||||
14 <br>
|
||||
15 <br>
|
||||
16 <br>
|
||||
17 <br>
|
||||
18 <br>
|
||||
19 <br>
|
||||
20 <br>
|
||||
21 <br>
|
||||
22 <br>
|
||||
23 <br>
|
||||
24 <br>
|
||||
25 <br>
|
||||
26 <br>
|
||||
27 <br>
|
||||
28 <br>
|
||||
29 <br>
|
||||
30 <br>
|
||||
31 <br>
|
||||
32 <br>
|
||||
33 <br>
|
||||
34 <br>
|
||||
35 <br>
|
||||
36 <br>
|
||||
37 <br>
|
||||
38 <br>
|
||||
39 <br>
|
||||
40 <br>
|
||||
|
||||
</p><p>
|
||||
1 <br>
|
||||
2 <br>
|
||||
3 <br>
|
||||
4 <br>
|
||||
5 <br>
|
||||
6 <br>
|
||||
7 <br>
|
||||
8 <br>
|
||||
9 <br>
|
||||
10 <br>
|
||||
11 <br>
|
||||
12 <br>
|
||||
13 <br>
|
||||
14 <br>
|
||||
15 <br>
|
||||
16 <br>
|
||||
17 <br>
|
||||
18 <br>
|
||||
19 <br>
|
||||
20 <br>
|
||||
21 <br>
|
||||
22 <br>
|
||||
23 <br>
|
||||
24 <br>
|
||||
25 <br>
|
||||
26 <br>
|
||||
27 <br>
|
||||
28 <br>
|
||||
29 <br>
|
||||
30 <br>
|
||||
31 <br>
|
||||
32 <br>
|
||||
33 <br>
|
||||
34 <br>
|
||||
35 <br>
|
||||
36 <br>
|
||||
37 <br>
|
||||
38 <br>
|
||||
39 <br>
|
||||
40 <br>
|
||||
|
||||
</p><p>
|
||||
1 <br>
|
||||
2 <br>
|
||||
3 <br>
|
||||
4 <br>
|
||||
5 <br>
|
||||
6 <br>
|
||||
7 <br>
|
||||
8 <br>
|
||||
9 <br>
|
||||
10 <br>
|
||||
11 <br>
|
||||
12 <br>
|
||||
13 <br>
|
||||
14 <br>
|
||||
15 <br>
|
||||
16 <br>
|
||||
17 <br>
|
||||
18 <br>
|
||||
19 <br>
|
||||
20 <br>
|
||||
21 <br>
|
||||
22 <br>
|
||||
23 <br>
|
||||
24 <br>
|
||||
25 <br>
|
||||
26 <br>
|
||||
27 <br>
|
||||
28 <br>
|
||||
29 <br>
|
||||
30 <br>
|
||||
31 <br>
|
||||
32 <br>
|
||||
33 <br>
|
||||
34 <br>
|
||||
35 <br>
|
||||
36 <br>
|
||||
37 <br>
|
||||
38 <br>
|
||||
39 <br>
|
||||
40 <br>
|
||||
|
||||
</p><p>
|
||||
1 <br>
|
||||
2 <br>
|
||||
3 <br>
|
||||
4 <br>
|
||||
5 <br>
|
||||
6 <br>
|
||||
7 <br>
|
||||
8 <br>
|
||||
9 <br>
|
||||
10 <br>
|
||||
11 <br>
|
||||
12 <br>
|
||||
13 <br>
|
||||
14 <br>
|
||||
15 <br>
|
||||
16 <br>
|
||||
17 <br>
|
||||
18 <br>
|
||||
19 <br>
|
||||
20 <br>
|
||||
21 <br>
|
||||
22 <br>
|
||||
23 <br>
|
||||
24 <br>
|
||||
25 <br>
|
||||
26 <br>
|
||||
27 <br>
|
||||
28 <br>
|
||||
29 <br>
|
||||
30 <br>
|
||||
31 <br>
|
||||
32 <br>
|
||||
33 <br>
|
||||
34 <br>
|
||||
35 <br>
|
||||
36 <br>
|
||||
37 <br>
|
||||
38 <br>
|
||||
39 <br>
|
||||
40 <br>
|
||||
|
||||
</p><p>
|
||||
1 <br>
|
||||
2 <br>
|
||||
3 <br>
|
||||
4 <br>
|
||||
5 <br>
|
||||
6 <br>
|
||||
7 <br>
|
||||
8 <br>
|
||||
9 <br>
|
||||
10 <br>
|
||||
11 <br>
|
||||
12 <br>
|
||||
13 <br>
|
||||
14 <br>
|
||||
15 <br>
|
||||
16 <br>
|
||||
17 <br>
|
||||
18 <br>
|
||||
19 <br>
|
||||
20 <br>
|
||||
21 <br>
|
||||
22 <br>
|
||||
23 <br>
|
||||
24 <br>
|
||||
25 <br>
|
||||
26 <br>
|
||||
27 <br>
|
||||
28 <br>
|
||||
29 <br>
|
||||
30 <br>
|
||||
31 <br>
|
||||
32 <br>
|
||||
33 <br>
|
||||
34 <br>
|
||||
35 <br>
|
||||
36 <br>
|
||||
37 <br>
|
||||
38 <br>
|
||||
39 <br>
|
||||
40 <br>
|
||||
|
||||
</p><p>
|
||||
1 <br>
|
||||
2 <br>
|
||||
3 <br>
|
||||
4 <br>
|
||||
5 <br>
|
||||
6 <br>
|
||||
7 <br>
|
||||
8 <br>
|
||||
9 <br>
|
||||
10 <br>
|
||||
11 <br>
|
||||
12 <br>
|
||||
13 <br>
|
||||
14 <br>
|
||||
15 <br>
|
||||
16 <br>
|
||||
17 <br>
|
||||
18 <br>
|
||||
19 <br>
|
||||
20 <br>
|
||||
21 <br>
|
||||
22 <br>
|
||||
23 <br>
|
||||
24 <br>
|
||||
25 <br>
|
||||
26 <br>
|
||||
27 <br>
|
||||
28 <br>
|
||||
29 <br>
|
||||
30 <br>
|
||||
31 <br>
|
||||
32 <br>
|
||||
33 <br>
|
||||
34 <br>
|
||||
35 <br>
|
||||
36 <br>
|
||||
37 <br>
|
||||
38 <br>
|
||||
39 <br>
|
||||
40 <br>
|
||||
|
||||
</p><p>
|
||||
1 <br>
|
||||
2 <br>
|
||||
3 <br>
|
||||
4 <br>
|
||||
5 <br>
|
||||
6 <br>
|
||||
7 <br>
|
||||
8 <br>
|
||||
9 <br>
|
||||
10 <br>
|
||||
11 <br>
|
||||
12 <br>
|
||||
13 <br>
|
||||
14 <br>
|
||||
15 <br>
|
||||
16 <br>
|
||||
17 <br>
|
||||
18 <br>
|
||||
19 <br>
|
||||
20 <br>
|
||||
21 <br>
|
||||
22 <br>
|
||||
23 <br>
|
||||
24 <br>
|
||||
25 <br>
|
||||
26 <br>
|
||||
27 <br>
|
||||
28 <br>
|
||||
29 <br>
|
||||
30 <br>
|
||||
31 <br>
|
||||
32 <br>
|
||||
33 <br>
|
||||
34 <br>
|
||||
35 <br>
|
||||
36 <br>
|
||||
37 <br>
|
||||
38 <br>
|
||||
39 <br>
|
||||
40 <br>
|
||||
|
||||
</p><p>
|
||||
1 <br>
|
||||
2 <br>
|
||||
3 <br>
|
||||
4 <br>
|
||||
5 <br>
|
||||
6 <br>
|
||||
7 <br>
|
||||
8 <br>
|
||||
9 <br>
|
||||
10 <br>
|
||||
11 <br>
|
||||
12 <br>
|
||||
13 <br>
|
||||
14 <br>
|
||||
15 <br>
|
||||
16 <br>
|
||||
17 <br>
|
||||
18 <br>
|
||||
19 <br>
|
||||
20 <br>
|
||||
21 <br>
|
||||
22 <br>
|
||||
23 <br>
|
||||
24 <br>
|
||||
25 <br>
|
||||
26 <br>
|
||||
27 <br>
|
||||
28 <br>
|
||||
29 <br>
|
||||
30 <br>
|
||||
31 <br>
|
||||
32 <br>
|
||||
33 <br>
|
||||
34 <br>
|
||||
35 <br>
|
||||
36 <br>
|
||||
37 <br>
|
||||
38 <br>
|
||||
39 <br>
|
||||
40 <br>
|
||||
|
||||
</p><p>
|
||||
1 <br>
|
||||
2 <br>
|
||||
3 <br>
|
||||
4 <br>
|
||||
5 <br>
|
||||
6 <br>
|
||||
7 <br>
|
||||
8 <br>
|
||||
9 <br>
|
||||
10 <br>
|
||||
11 <br>
|
||||
12 <br>
|
||||
13 <br>
|
||||
14 <br>
|
||||
15 <br>
|
||||
16 <br>
|
||||
17 <br>
|
||||
18 <br>
|
||||
19 <br>
|
||||
20 <br>
|
||||
21 <br>
|
||||
22 <br>
|
||||
23 <br>
|
||||
24 <br>
|
||||
25 <br>
|
||||
26 <br>
|
||||
27 <br>
|
||||
28 <br>
|
||||
29 <br>
|
||||
30 <br>
|
||||
31 <br>
|
||||
32 <br>
|
||||
33 <br>
|
||||
34 <br>
|
||||
35 <br>
|
||||
36 <br>
|
||||
37 <br>
|
||||
38 <br>
|
||||
39 <br>
|
||||
40 <br>
|
||||
|
||||
</p>
|
||||
</div>
|
||||
<script clss="testbody" type="text/javascript;version=1.7">
|
||||
function ScrollTops() {
|
||||
this.outerScrollTop = document.getElementById('iframe-body').scrollTop;
|
||||
this.innerScrollTop = document.getElementById('subframe').scrollTop;
|
||||
}
|
||||
|
||||
var DefaultEvent = {
|
||||
deltaMode: WheelEvent.DOM_DELTA_LINE,
|
||||
deltaX: 0, deltaY: 1,
|
||||
lineOrPageDeltaX: 0, lineOrPageDeltaY: 1,
|
||||
};
|
||||
|
||||
function test() {
|
||||
var subframe = document.getElementById('subframe');
|
||||
var oldpos = new ScrollTops();
|
||||
sendWheelAndPaint(subframe, 10, 10, DefaultEvent, function () {
|
||||
var newpos = new ScrollTops();
|
||||
ok(oldpos.outerScrollTop == newpos.outerScrollTop, "viewport should not have scrolled");
|
||||
ok(oldpos.innerScrollTop != newpos.innerScrollTop, "subframe should have scrolled");
|
||||
doOuterScroll(subframe, newpos);
|
||||
});
|
||||
}
|
||||
|
||||
function doOuterScroll(subframe, oldpos) {
|
||||
var outer = document.getElementById('iframe-body');
|
||||
sendWheelAndPaint(outer, 20, 5, DefaultEvent, function () {
|
||||
var newpos = new ScrollTops();
|
||||
ok(oldpos.outerScrollTop != newpos.outerScrollTop, "viewport should have scrolled");
|
||||
ok(oldpos.innerScrollTop == newpos.innerScrollTop, "subframe should not have scrolled");
|
||||
doInnerScrollAgain(subframe, newpos);
|
||||
});
|
||||
}
|
||||
|
||||
function doInnerScrollAgain(subframe, oldpos) {
|
||||
sendWheelAndPaint(subframe, 10, 10, DefaultEvent, function () {
|
||||
var newpos = new ScrollTops();
|
||||
ok(oldpos.outerScrollTop == newpos.outerScrollTop, "viewport should not have scrolled");
|
||||
ok(oldpos.innerScrollTop != newpos.innerScrollTop, "subframe should have scrolled");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.testInChaosMode();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
pushPrefs([['general.smoothScroll', false],
|
||||
['mousewheel.transaction.timeout', 0],
|
||||
['mousewheel.transaction.ignoremovedelay', 0]])
|
||||
.then(waitUntilApzStable)
|
||||
.then(test);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test scrolling flattened inactive frames</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="container" style="height: 300px; width: 600px; overflow: auto; background: yellow">
|
||||
<div id="outer" style="height: 400px; width: 500px; overflow: auto; background: black">
|
||||
<div id="inner" style="mix-blend-mode: screen; height: 800px; overflow: auto; background: purple">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script class="testbody" type="text/javascript;version=1.7">
|
||||
function test() {
|
||||
var container = document.getElementById('container');
|
||||
var outer = document.getElementById('outer');
|
||||
var inner = document.getElementById('inner');
|
||||
var outerScrollTop = outer.scrollTop;
|
||||
var containerScrollTop = container.scrollTop;
|
||||
var event = {
|
||||
deltaMode: WheelEvent.DOM_DELTA_LINE,
|
||||
deltaX: 0,
|
||||
deltaY: 10,
|
||||
lineOrPageDeltaX: 0,
|
||||
lineOrPageDeltaY: 10,
|
||||
};
|
||||
sendWheelAndPaint(inner, 20, 30, event, function () {
|
||||
ok(container.scrollTop == containerScrollTop, "container scrollframe should not have scrolled");
|
||||
ok(outer.scrollTop > outerScrollTop, "nested scrollframe should have scrolled");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.testInChaosMode();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
pushPrefs([['general.smoothScroll', false],
|
||||
['mousewheel.transaction.timeout', 1000000]])
|
||||
.then(waitUntilApzStable)
|
||||
.then(test);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test scrolling subframe scrollbars</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<style>
|
||||
p {
|
||||
width:200px;
|
||||
height:200px;
|
||||
border:solid 1px black;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p id="subframe">
|
||||
1 <br>
|
||||
2 <br>
|
||||
3 <br>
|
||||
4 <br>
|
||||
5 <br>
|
||||
6 <br>
|
||||
7 <br>
|
||||
8 <br>
|
||||
9 <br>
|
||||
10 <br>
|
||||
11 <br>
|
||||
12 <br>
|
||||
13 <br>
|
||||
14 <br>
|
||||
15 <br>
|
||||
16 <br>
|
||||
17 <br>
|
||||
18 <br>
|
||||
19 <br>
|
||||
20 <br>
|
||||
21 <br>
|
||||
22 <br>
|
||||
23 <br>
|
||||
24 <br>
|
||||
25 <br>
|
||||
26 <br>
|
||||
27 <br>
|
||||
28 <br>
|
||||
29 <br>
|
||||
30 <br>
|
||||
31 <br>
|
||||
32 <br>
|
||||
33 <br>
|
||||
34 <br>
|
||||
35 <br>
|
||||
36 <br>
|
||||
37 <br>
|
||||
38 <br>
|
||||
39 <br>
|
||||
40 <br>
|
||||
</p>
|
||||
<script clss="testbody" type="text/javascript;version=1.7">
|
||||
|
||||
var DefaultEvent = {
|
||||
deltaMode: WheelEvent.DOM_DELTA_LINE,
|
||||
deltaX: 0, deltaY: 1,
|
||||
lineOrPageDeltaX: 0, lineOrPageDeltaY: 1,
|
||||
};
|
||||
|
||||
var ScrollbarWidth = 0;
|
||||
|
||||
function test() {
|
||||
var subframe = document.getElementById('subframe');
|
||||
var oldClientWidth = subframe.clientWidth;
|
||||
|
||||
subframe.style.overflow = 'auto';
|
||||
subframe.getBoundingClientRect();
|
||||
|
||||
waitForAllPaintsFlushed(function () {
|
||||
ScrollbarWidth = oldClientWidth - subframe.clientWidth;
|
||||
if (!ScrollbarWidth) {
|
||||
// Probably we have overlay scrollbars - abort the test.
|
||||
ok(true, "overlay scrollbars - skipping test");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
ok(subframe.scrollHeight > subframe.clientHeight, "subframe should have scrollable content");
|
||||
testScrolling(subframe);
|
||||
});
|
||||
}
|
||||
|
||||
function testScrolling(subframe) {
|
||||
// Send a wheel event roughly to where we think the trackbar is. We pick a
|
||||
// point at the bottom, in the middle of the trackbar, where the slider is
|
||||
// unlikely to be (since it starts at the top).
|
||||
var posX = subframe.clientWidth + (ScrollbarWidth / 2);
|
||||
var posY = subframe.clientHeight - 20;
|
||||
|
||||
var oldScrollTop = subframe.scrollTop;
|
||||
|
||||
sendWheelAndPaint(subframe, posX, posY, DefaultEvent, function () {
|
||||
ok(subframe.scrollTop > oldScrollTop, "subframe should have scrolled");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
pushPrefs([['general.smoothScroll', false],
|
||||
['mousewheel.transaction.timeout', 0],
|
||||
['mousewheel.transaction.ignoremovedelay', 0]])
|
||||
.then(waitUntilApzStable)
|
||||
.then(test);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
77
gfx/layers/apz/test/mochitest/test_smoothness.html
Normal file
77
gfx/layers/apz/test/mochitest/test_smoothness.html
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Test Frame Uniformity While Scrolling</title>
|
||||
<script type="text/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
|
||||
<style>
|
||||
#content {
|
||||
height: 5000px;
|
||||
background: repeating-linear-gradient(#EEE, #EEE 100px, #DDD 100px, #DDD 200px);
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
var scrollEvents = 100;
|
||||
var i = 0;
|
||||
var testPref = "gfx.vsync.collect-scroll-transforms";
|
||||
// Scroll points
|
||||
var x = 100;
|
||||
var y = 150;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var utils = _getDOMWindowUtils(window);
|
||||
|
||||
function sendScrollEvent(aRafTimestamp) {
|
||||
var scrollDiv = document.getElementById("content");
|
||||
|
||||
if (i < scrollEvents) {
|
||||
i++;
|
||||
// Scroll diff
|
||||
var dx = 0;
|
||||
var dy = -10; // Negative to scroll down
|
||||
synthesizeNativeWheelAndWaitForWheelEvent(scrollDiv, x, y, dx, dy);
|
||||
window.requestAnimationFrame(sendScrollEvent);
|
||||
} else {
|
||||
// Locally, with silk and apz + e10s, retina 15" mbp usually get ~1.0 - 1.5
|
||||
// w/o silk + e10s + apz, I get up to 7. Lower is better.
|
||||
// Windows, I get ~3. Values are not valid w/o hardware vsync
|
||||
var uniformities = _getDOMWindowUtils().getFrameUniformityTestData();
|
||||
for (var j = 0; j < uniformities.layerUniformities.length; j++) {
|
||||
var layerResult = uniformities.layerUniformities[j];
|
||||
var layerAddr = layerResult.layerAddress;
|
||||
var uniformity = layerResult.frameUniformity;
|
||||
var msg = "Layer: " + layerAddr.toString(16) + " Uniformity: " + uniformity;
|
||||
SimpleTest.ok((uniformity >= 0) && (uniformity < 4.0), msg);
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
window.requestAnimationFrame(sendScrollEvent);
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
var apzEnabled = SpecialPowers.getBoolPref("layers.async-pan-zoom.enabled");
|
||||
if (!apzEnabled) {
|
||||
SimpleTest.ok(true, "APZ not enabled, skipping test");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set" : [
|
||||
[testPref, true]
|
||||
]
|
||||
}, startTest);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="content">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1203140
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1203140</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1203140">Mozilla Bug 1203140</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="overflow-y:scroll; height: 400px">
|
||||
<p>The box below has a touch listener and a passive wheel listener. With touch events disabled, APZ shouldn't wait for any listeners.</p>
|
||||
<div id="box" style="width: 200px; height: 200px; background-color: blue"></div>
|
||||
<div style="height: 1000px; width: 10px">Div to make 'content' scrollable</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
const kResponseTimeoutMs = 2 * 60 * 1000; // 2 minutes
|
||||
|
||||
function takeSnapshots(e) {
|
||||
// Grab some snapshots, and make sure some of them are different (i.e. check
|
||||
// the page is scrolling in the compositor, concurrently with this wheel
|
||||
// listener running).
|
||||
// Note that we want this function to take less time than the content response
|
||||
// timeout, otherwise the scrolling will start even if we haven't returned,
|
||||
// and that would invalidate purpose of the test.
|
||||
var start = Date.now();
|
||||
var lastSnapshot = null;
|
||||
var success = false;
|
||||
|
||||
// Get the position of the 'content' div relative to the screen
|
||||
var rect = rectRelativeToScreen(document.getElementById('content'));
|
||||
|
||||
for (var i = 0; i < 10; i++) {
|
||||
SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(16);
|
||||
var snapshot = getSnapshot(rect);
|
||||
//dump("Took snapshot " + snapshot + "\n"); // this might help with debugging
|
||||
|
||||
if (lastSnapshot && lastSnapshot != snapshot) {
|
||||
ok(true, "Found some different pixels in snapshot " + i + " compared to previous");
|
||||
success = true;
|
||||
}
|
||||
lastSnapshot = snapshot;
|
||||
}
|
||||
ok(success, "Found some snapshots that were different");
|
||||
ok((Date.now() - start) < kResponseTimeoutMs, "Snapshotting ran quickly enough");
|
||||
|
||||
// Until now, no scroll events will have been dispatched to content. That's
|
||||
// because scroll events are dispatched on the main thread, which we've been
|
||||
// hogging with the code above. At this point we restore the normal refresh
|
||||
// behaviour and let the main thread go back to C++ code, so the scroll events
|
||||
// fire and we unwind from the main test continuation.
|
||||
SpecialPowers.DOMWindowUtils.restoreNormalRefresh();
|
||||
}
|
||||
|
||||
function* test(testDriver) {
|
||||
var box = document.getElementById('box');
|
||||
|
||||
// Ensure the div is layerized by scrolling it
|
||||
yield moveMouseAndScrollWheelOver(box, 10, 10, testDriver);
|
||||
|
||||
box.addEventListener('touchstart', function(e) {
|
||||
ok(false, "This should never be run");
|
||||
}, false);
|
||||
box.addEventListener('wheel', takeSnapshots, { capture: false, passive: true });
|
||||
|
||||
// Let the event regions and layerization propagate to the APZ
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(testDriver);
|
||||
});
|
||||
|
||||
// Take over control of the refresh driver and compositor
|
||||
var utils = SpecialPowers.DOMWindowUtils;
|
||||
utils.advanceTimeAndRefresh(0);
|
||||
|
||||
// Trigger an APZ scroll using a wheel event. If APZ is waiting for a
|
||||
// content response, it will wait for takeSnapshots to finish running before
|
||||
// it starts scrolling, which will cause the checks in takeSnapshots to fail.
|
||||
yield synthesizeNativeMouseMoveAndWaitForMoveEvent(box, 10, 10, testDriver);
|
||||
yield synthesizeNativeWheelAndWaitForScrollEvent(box, 10, 10, 0, -50, testDriver);
|
||||
}
|
||||
|
||||
if (isApzEnabled()) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
// Disable touch events, so that APZ knows not to wait for touch listeners.
|
||||
// Also explicitly set the content response timeout, so we know how long it
|
||||
// is (see comment in takeSnapshots).
|
||||
// Finally, enable smooth scrolling, so that the wheel-scroll we do as part
|
||||
// of the test triggers an APZ animation rather than doing an instant scroll.
|
||||
// Note that this pref doesn't work for the synthesized wheel events on OS X,
|
||||
// those are hard-coded to be instant scrolls.
|
||||
pushPrefs([["dom.w3c_touch_events.enabled", 0],
|
||||
["apz.content_response_timeout", kResponseTimeoutMs],
|
||||
["general.smoothscroll", true]])
|
||||
.then(waitUntilApzStable)
|
||||
.then(runContinuation(test))
|
||||
.then(SimpleTest.finish);
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
106
gfx/layers/apz/test/mochitest/test_wheel_scroll.html
Normal file
106
gfx/layers/apz/test/mochitest/test_wheel_scroll.html
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1013412
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1013412</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
#content {
|
||||
height: 800px;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
#scroller {
|
||||
height: 2000px;
|
||||
background: repeating-linear-gradient(#EEE, #EEE 100px, #DDD 100px, #DDD 200px);
|
||||
}
|
||||
|
||||
#scrollbox {
|
||||
margin-top: 200px;
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
border-radius: 250px;
|
||||
box-shadow: inset 0 0 0 60px #555;
|
||||
background: #777;
|
||||
}
|
||||
|
||||
#circle {
|
||||
position: relative;
|
||||
left: 240px;
|
||||
top: 20px;
|
||||
border: 10px solid white;
|
||||
border-radius: 10px;
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
transform-origin: 10px 230px;
|
||||
will-change: transform;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1161206">Mozilla Bug 1161206</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<p>Scrolling the page should be async, but scrolling over the dark circle should not scroll the page and instead rotate the white ball.</p>
|
||||
<div id="scroller">
|
||||
<div id="scrollbox">
|
||||
<div id="circle"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var rotation = 0;
|
||||
var rotationAdjusted = false;
|
||||
|
||||
var incrementForMode = function (mode) {
|
||||
switch (mode) {
|
||||
case WheelEvent.DOM_DELTA_PIXEL: return 1;
|
||||
case WheelEvent.DOM_DELTA_LINE: return 15;
|
||||
case WheelEvent.DOM_DELTA_PAGE: return 400;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
document.getElementById("scrollbox").addEventListener("wheel", function (e) {
|
||||
rotation += e.deltaY * incrementForMode(e.deltaMode) * 0.2;
|
||||
document.getElementById("circle").style.transform = "rotate(" + rotation + "deg)";
|
||||
rotationAdjusted = true;
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
function* test(testDriver) {
|
||||
var content = document.getElementById('content');
|
||||
for (i = 0; i < 300; i++) { // enough iterations that we would scroll to the bottom of 'content'
|
||||
yield synthesizeNativeWheelAndWaitForWheelEvent(content, 100, 150, 0, -5, testDriver);
|
||||
}
|
||||
var scrollbox = document.getElementById('scrollbox');
|
||||
is(content.scrollTop > 0, true, "We should have scrolled down somewhat");
|
||||
is(content.scrollTop < content.scrollTopMax, true, "We should not have scrolled to the bottom of the scrollframe");
|
||||
is(rotationAdjusted, true, "The rotation should have been adjusted");
|
||||
}
|
||||
|
||||
SimpleTest.testInChaosMode();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// If we allow smooth scrolling the "smooth" scrolling may cause the page to
|
||||
// glide past the scrollbox (which is supposed to stop the scrolling) and so
|
||||
// we might end up at the bottom of the page.
|
||||
pushPrefs([["general.smoothScroll", false]])
|
||||
.then(waitUntilApzStable)
|
||||
.then(runContinuation(test))
|
||||
.then(SimpleTest.finish);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
137
gfx/layers/apz/test/mochitest/test_wheel_transactions.html
Normal file
137
gfx/layers/apz/test/mochitest/test_wheel_transactions.html
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1175585
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1175585</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
#outer-frame {
|
||||
height: 500px;
|
||||
overflow: scroll;
|
||||
background: repeating-linear-gradient(#CCC, #CCC 100px, #BBB 100px, #BBB 200px);
|
||||
}
|
||||
#inner-frame {
|
||||
margin-top: 25%;
|
||||
height: 200%;
|
||||
width: 75%;
|
||||
overflow: scroll;
|
||||
}
|
||||
#inner-content {
|
||||
height: 200%;
|
||||
width: 200%;
|
||||
background: repeating-linear-gradient(#EEE, #EEE 100px, #DDD 100px, #DDD 200px);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1175585">APZ wheel transactions test</a>
|
||||
<p id="display"></p>
|
||||
<div id="outer-frame">
|
||||
<div id="inner-frame">
|
||||
<div id="inner-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function scrollWheelOver(element, deltaY, testDriver) {
|
||||
synthesizeNativeWheelAndWaitForScrollEvent(element, 10, 10, 0, deltaY, testDriver);
|
||||
}
|
||||
|
||||
function* test(testDriver) {
|
||||
var outer = document.getElementById('outer-frame');
|
||||
var inner = document.getElementById('inner-frame');
|
||||
var innerContent = document.getElementById('inner-content');
|
||||
|
||||
// Register a wheel event listener that records the target of
|
||||
// the last wheel event, so that we can make assertions about it.
|
||||
var lastWheelTarget;
|
||||
var wheelTargetRecorder = function(e) { lastWheelTarget = e.target; };
|
||||
window.addEventListener("wheel", wheelTargetRecorder);
|
||||
|
||||
// Scroll |outer| to the bottom.
|
||||
while (outer.scrollTop < outer.scrollTopMax) {
|
||||
yield scrollWheelOver(outer, -10, testDriver);
|
||||
}
|
||||
|
||||
// Verify that this has brought |inner| under the wheel.
|
||||
is(lastWheelTarget, innerContent, "'inner-content' should have been brought under the wheel");
|
||||
window.removeEventListener("wheel", wheelTargetRecorder);
|
||||
|
||||
// Immediately after, scroll it back up a bit.
|
||||
yield scrollWheelOver(outer, 10, testDriver);
|
||||
|
||||
// Check that it was |outer| that scrolled back, and |inner| didn't
|
||||
// scroll at all, as all the above scrolls should be in the same
|
||||
// transaction.
|
||||
ok(outer.scrollTop < outer.scrollTopMax, "'outer' should have scrolled back a bit");
|
||||
is(inner.scrollTop, 0, "'inner' should not have scrolled");
|
||||
|
||||
// The next part of the test is related to the transaction timeout.
|
||||
// Turn it down a bit so waiting for the timeout to elapse doesn't
|
||||
// slow down the test harness too much.
|
||||
var timeout = 5;
|
||||
yield SpecialPowers.pushPrefEnv({"set": [["mousewheel.transaction.timeout", timeout]]}, testDriver);
|
||||
SimpleTest.requestFlakyTimeout("we are testing code that measures actual elapsed time between two events");
|
||||
|
||||
// Scroll up a bit more. It's still |outer| scrolling because
|
||||
// |inner| is still scrolled all the way to the top.
|
||||
yield scrollWheelOver(outer, 10, testDriver);
|
||||
|
||||
// Wait for the transaction timeout to elapse.
|
||||
// timeout * 5 is used to make it less likely that the timeout is less than
|
||||
// the system timestamp resolution
|
||||
yield window.setTimeout(testDriver, timeout * 5);
|
||||
|
||||
// Now scroll down. The transaction having timed out, the event
|
||||
// should pick up a new target, and that should be |inner|.
|
||||
yield scrollWheelOver(outer, -10, testDriver);
|
||||
ok(inner.scrollTop > 0, "'inner' should have been scrolled");
|
||||
|
||||
// Finally, test scroll handoff after a timeout.
|
||||
|
||||
// Continue scrolling |inner| down to the bottom.
|
||||
var prevScrollTop = inner.scrollTop;
|
||||
while (inner.scrollTop < inner.scrollTopMax) {
|
||||
yield scrollWheelOver(outer, -10, testDriver);
|
||||
// Avoid a failure getting us into an infinite loop.
|
||||
ok(inner.scrollTop > prevScrollTop, "scrolling down should increase scrollTop");
|
||||
prevScrollTop = inner.scrollTop;
|
||||
}
|
||||
|
||||
// Wait for the transaction timeout to elapse.
|
||||
// timeout * 5 is used to make it less likely that the timeout is less than
|
||||
// the system timestamp resolution
|
||||
yield window.setTimeout(testDriver, timeout * 5);
|
||||
|
||||
// Continued downward scrolling should scroll |outer| to the bottom.
|
||||
prevScrollTop = outer.scrollTop;
|
||||
while (outer.scrollTop < outer.scrollTopMax) {
|
||||
yield scrollWheelOver(outer, -10, testDriver);
|
||||
// Avoid a failure getting us into an infinite loop.
|
||||
ok(outer.scrollTop > prevScrollTop, "scrolling down should increase scrollTop");
|
||||
prevScrollTop = outer.scrollTop;
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Disable smooth scrolling because it makes the test flaky (we don't have a good
|
||||
// way of detecting when the scrolling is finished).
|
||||
pushPrefs([["general.smoothScroll", false]])
|
||||
.then(waitUntilApzStable)
|
||||
.then(runContinuation(test))
|
||||
.then(SimpleTest.finish);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue