Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
Services.scriptloader.loadSubScript(
this
);
async function waitForWhile() {
await new Promise(resolve => {
requestIdleCallback(resolve, { timeout: 300 });
});
await new Promise(r => requestAnimationFrame(r));
}
add_setup(async function () {
await SpecialPowers.pushPrefEnv({
set: [
["browser.gesture.swipe.left", "Browser:BackOrBackDuplicate"],
["browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate"],
["widget.disable-swipe-tracker", false],
["widget.swipe.touchscreen.enabled", true],
["widget.swipe.velocity-twitch-tolerance", 0.0000001],
["widget.swipe.success-velocity-contribution", 0.0],
["widget.swipe.pixel-size", 100.0],
["apz.touch_start_tolerance", 0.0],
["apz.touch_move_tolerance", 0.0],
["apz.overscroll.enabled", true],
["apz.test.logging_enabled", true],
],
});
});
add_task(
async function test_pan_scroll_after_touchscreen_swipe_ends_in_the_middle() {
const firstPage = "about:about";
const tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
firstPage,
true /* waitForLoad */
);
const URL_ROOT = getRootDirectory(gTestPath).replace(
);
BrowserTestUtils.startLoadingURIString(
tab.linkedBrowser,
URL_ROOT + "helper_swipe_gesture.html"
);
await BrowserTestUtils.browserLoaded(
tab.linkedBrowser,
false /* includeSubFrames */,
URL_ROOT + "helper_swipe_gesture.html"
);
ok(gBrowser.webNavigation.canGoBack);
ok(!gBrowser.webNavigation.canGoForward);
await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
ok(
content.document.documentElement.scrollLeft == 0 &&
content.document.documentElement.scrollLeftMax > 0,
"the page is on the left edge and it is scrollable in the right"
);
});
const { TOUCH_CONTACT, TOUCH_REMOVE } = SpecialPowers.DOMWindowUtils;
// End the swipe before it reaches the navigation threshold.
await synthesizeNativeTouch(tab.linkedBrowser, 100, 100, TOUCH_CONTACT);
await synthesizeNativeTouch(tab.linkedBrowser, 105, 100, TOUCH_CONTACT);
await synthesizeNativeTouch(tab.linkedBrowser, 110, 100, TOUCH_CONTACT);
await synthesizeNativeTouch(tab.linkedBrowser, 110, 100, TOUCH_REMOVE);
await waitForWhile();
is(
tab.linkedBrowser.currentURI.spec,
URL_ROOT + "helper_swipe_gesture.html",
"The canceled swipe does not navigate"
);
await panRightToLeftBegin(tab.linkedBrowser, 100, 100, 1);
await panRightToLeftEnd(tab.linkedBrowser, 100, 100);
await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
await content.wrappedJSObject.promiseApzFlushedRepaints();
Assert.greater(
content.document.documentElement.scrollLeft,
0,
"The touchpad scrolls after the touchscreen swipe should scroll the page"
);
});
BrowserTestUtils.removeTab(tab);
}
);
// Verify that canceling a touchscreen swipe releases the swipe tracker.
// Otherwise, it consumes the next touchpad pan as part of the canceled swipe
// instead of scrolling. See nsIWidget::HandleTouchInputAsSwipe().
add_task(async function test_pan_scroll_after_touchscreen_swipe_cancellation() {
await SpecialPowers.pushPrefEnv({
set: [
// On Windows, nsWindow::SynthesizeNativeTouchPoint() injects touches via
// InjectTouchInput(), and nsWindow::OnTouch() converts the resulting
// WM_TOUCH into MultiTouchInput. WM_TOUCH has no cancel flag (POINTER_FLAG_CANCELED),
// so OnTouch() turns TOUCH_CANCEL into MULTITOUCH_END.
// Dispatch the touches directly through nsIWidget::DispatchTouchInput() instead.
["apz.test.fails_with_native_injection", AppConstants.platform == "win"],
],
});
const firstPage = "about:about";
const tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
firstPage,
true /* waitForLoad */
);
const URL_ROOT = getRootDirectory(gTestPath).replace(
);
BrowserTestUtils.startLoadingURIString(
tab.linkedBrowser,
URL_ROOT + "helper_swipe_gesture.html"
);
await BrowserTestUtils.browserLoaded(
tab.linkedBrowser,
false /* includeSubFrames */,
URL_ROOT + "helper_swipe_gesture.html"
);
ok(gBrowser.webNavigation.canGoBack);
ok(!gBrowser.webNavigation.canGoForward);
await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
ok(
content.document.documentElement.scrollLeft == 0 &&
content.document.documentElement.scrollLeftMax > 0,
"the page is on the left edge and it is scrollable in the right"
);
});
const { TOUCH_CONTACT, TOUCH_CANCEL } = SpecialPowers.DOMWindowUtils;
await synthesizeNativeTouch(tab.linkedBrowser, 100, 100, TOUCH_CONTACT);
await synthesizeNativeTouch(tab.linkedBrowser, 200, 100, TOUCH_CONTACT);
await synthesizeNativeTouch(tab.linkedBrowser, 300, 100, TOUCH_CONTACT);
await synthesizeNativeTouch(tab.linkedBrowser, 300, 100, TOUCH_CANCEL);
await waitForWhile();
is(
tab.linkedBrowser.currentURI.spec,
URL_ROOT + "helper_swipe_gesture.html",
"The canceled swipe does not navigate"
);
await panRightToLeftBegin(tab.linkedBrowser, 100, 100, 1);
await panRightToLeftEnd(tab.linkedBrowser, 100, 100);
await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
await content.wrappedJSObject.promiseApzFlushedRepaints();
Assert.greater(
content.document.documentElement.scrollLeft,
0,
"The touchpad scrolls after the touchscreen swipe should scroll the page"
);
});
BrowserTestUtils.removeTab(tab);
await SpecialPowers.popPrefEnv();
});
// Verify that touchpad input during an ongoing touchscreen swipe neither
// interrupts nor scrolls, and the touchscreen swipe still completes.
add_task(
async function test_touchpad_input_does_not_interrupt_ongoing_touchscreen_swipe() {
const URL_ROOT = getRootDirectory(gTestPath).replace(
);
const secondPage = URL_ROOT + "helper_swipe_gesture.html";
const firstPage = secondPage + "?previous";
const tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
firstPage
);
const { TOUCH_CONTACT, TOUCH_REMOVE } = SpecialPowers.DOMWindowUtils;
BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, secondPage);
await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, secondPage);
ok(tab.linkedBrowser.webNavigation.canGoBack);
await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
await content.wrappedJSObject.promiseApzFlushedRepaints();
ok(
content.document.documentElement.scrollLeft == 0 &&
content.document.documentElement.scrollLeftMax > 0,
"The page is at the left edge and can scroll right"
);
});
await synthesizeNativeTouch(tab.linkedBrowser, 100, 100, TOUCH_CONTACT);
await synthesizeNativeTouch(tab.linkedBrowser, 200, 100, TOUCH_CONTACT);
await waitForWhile();
await panLeftToRight(tab.linkedBrowser, 100, 100, 1);
await waitForWhile();
is(
tab.linkedBrowser.currentURI.spec,
secondPage,
"Touchpad input does not navigate while the finger remains on the screen"
);
await panRightToLeft(tab.linkedBrowser, 100, 100, 1);
await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
await content.wrappedJSObject.promiseApzFlushedRepaints();
is(
content.document.documentElement.scrollLeft,
0,
"Touchpad input does not scroll during the touchscreen swipe"
);
});
await synthesizeNativeTouch(tab.linkedBrowser, 300, 100, TOUCH_CONTACT);
const navigated = Promise.all([
BrowserTestUtils.browserStarted(tab.linkedBrowser, firstPage),
BrowserTestUtils.browserStopped(tab.linkedBrowser, firstPage),
]);
await synthesizeNativeTouch(tab.linkedBrowser, 300, 100, TOUCH_REMOVE);
await navigated;
is(
tab.linkedBrowser.currentURI.spec,
firstPage,
"Lifting the finger completes the touchscreen swipe"
);
BrowserTestUtils.removeTab(tab);
}
);
// The reverse of the test above: touchscreen input during an ongoing touchpad
// swipe does not interrupt it, and the touchpad swipe still completes.
// Unlike touchpad input, touchscreen input can still scroll the page during the
// swipe. See bug 2088133.
add_task(
async function test_touchscreen_input_does_not_interrupt_ongoing_touchpad_swipe() {
const URL_ROOT = getRootDirectory(gTestPath).replace(
);
const secondPage = URL_ROOT + "helper_swipe_gesture.html";
const firstPage = secondPage + "?previous";
const tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
firstPage
);
const { TOUCH_CONTACT, TOUCH_REMOVE } = SpecialPowers.DOMWindowUtils;
BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, secondPage);
await BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, secondPage);
ok(tab.linkedBrowser.webNavigation.canGoBack);
await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
await content.wrappedJSObject.promiseApzFlushedRepaints();
ok(
content.document.documentElement.scrollLeft == 0 &&
content.document.documentElement.scrollLeftMax > 0,
"The page is at the left edge and can scroll right"
);
});
await panLeftToRightBegin(tab.linkedBrowser, 100, 100, 1);
await panLeftToRightUpdate(tab.linkedBrowser, 100, 100, 1);
await waitForWhile();
await synthesizeNativeTouch(tab.linkedBrowser, 100, 100, TOUCH_CONTACT);
await synthesizeNativeTouch(tab.linkedBrowser, 200, 100, TOUCH_CONTACT);
await synthesizeNativeTouch(tab.linkedBrowser, 300, 100, TOUCH_CONTACT);
await synthesizeNativeTouch(tab.linkedBrowser, 300, 100, TOUCH_REMOVE);
await waitForWhile();
is(
tab.linkedBrowser.currentURI.spec,
secondPage,
"Touchscreen input does not navigate while the fingers remain on the touchpad"
);
const navigated = Promise.all([
BrowserTestUtils.browserStarted(tab.linkedBrowser, firstPage),
BrowserTestUtils.browserStopped(tab.linkedBrowser, firstPage),
]);
await panLeftToRightEnd(tab.linkedBrowser, 100, 100);
await navigated;
is(
tab.linkedBrowser.currentURI.spec,
firstPage,
"Lifting the fingers from the touchpad completes the touchpad swipe"
);
BrowserTestUtils.removeTab(tab);
}
);