<?xml version="1.0"?> <?xml-stylesheet href="chrome://global/skin" type="text/css"?> <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?> <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=378028 --> <window title="Mozilla Bug 378028" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/> <script src="chrome://mochikit/content/tests/SimpleTest/paint_listener.js"/> <!-- test results are displayed in the html:body --> <body xmlns="http://www.w3.org/1999/xhtml"> <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=378028" target="_blank">Mozilla Bug 378028</a> </body> <!-- richlistbox currently has no way of giving us a defined number of rows, so we just choose an arbitrary height limit that should give us plenty of vertical scrollability --> <richlistbox id="richlistbox" style="height:50px;"> <richlistitem id="richlistbox_item0" hidden="true"><label value="Item 0"/></richlistitem> <richlistitem id="richlistbox_item1"><label value="Item 1"/></richlistitem> <richlistitem id="richlistbox_item2"><label value="Item 2"/></richlistitem> <richlistitem id="richlistbox_item3"><label value="Item 3"/></richlistitem> <richlistitem id="richlistbox_item4"><label value="Item 4"/></richlistitem> <richlistitem id="richlistbox_item5"><label value="Item 5"/></richlistitem> <richlistitem id="richlistbox_item6"><label value="Item 6"/></richlistitem> <richlistitem id="richlistbox_item7"><label value="Item 7"/></richlistitem> <richlistitem id="richlistbox_item8"><label value="Item 8"/></richlistitem> </richlistbox> <box orient="horizontal"> <arrowscrollbox id="hscrollbox" clicktoscroll="true" orient="horizontal" smoothscroll="false" style="max-width:80px;" flex="1"> <hbox style="min-width:40px; min-height:20px; background:black;" hidden="true"/> <hbox style="min-width:40px; min-height:20px; background:white;"/> <hbox style="min-width:40px; min-height:20px; background:black;"/> <hbox style="min-width:40px; min-height:20px; background:white;"/> <hbox style="min-width:40px; min-height:20px; background:black;"/> <hbox style="min-width:40px; min-height:20px; background:white;"/> <hbox style="min-width:40px; min-height:20px; background:black;"/> <hbox style="min-width:40px; min-height:20px; background:white;"/> <hbox style="min-width:40px; min-height:20px; background:black;"/> </arrowscrollbox> </box> <arrowscrollbox id="vscrollbox" clicktoscroll="true" orient="vertical" smoothscroll="false" style="max-height:80px;" flex="1"> <vbox style="min-width:100px; min-height:40px; background:black;" hidden="true"/> <vbox style="min-width:100px; min-height:40px; background:white;"/> <vbox style="min-width:100px; min-height:40px; background:black;"/> <vbox style="min-width:100px; min-height:40px; background:white;"/> <vbox style="min-width:100px; min-height:40px; background:black;"/> <vbox style="min-width:100px; min-height:40px; background:white;"/> <vbox style="min-width:100px; min-height:40px; background:black;"/> <vbox style="min-width:100px; min-height:40px; background:white;"/> <vbox style="min-width:100px; min-height:40px; background:black;"/> <vbox style="min-width:100px; min-height:40px; background:white;"/> <vbox style="min-width:100px; min-height:40px; background:black;"/> </arrowscrollbox> <!-- test code goes here --> <script type="application/javascript"><![CDATA[ /** Test for Bug 378028 **/ /* and for Bug 350471 **/ SimpleTest.waitForExplicitFinish(); SimpleTest.waitForFocus(prepareRunningTests); // Some tests need to wait until stopping scroll completely. At this time, // setTimeout() will retry to check up to MAX_RETRY_COUNT times. const MAX_RETRY_COUNT = 5; const deltaModes = [ WheelEvent.DOM_DELTA_PIXEL, // 0 WheelEvent.DOM_DELTA_LINE, // 1 WheelEvent.DOM_DELTA_PAGE // 2 ]; function sendWheelAndWait(aScrollTaget, aX, aY, aEvent, aChecker) { function continueTestsIfScrolledAsExpected() { if (!aChecker()) SimpleTest.executeSoon(()=>{ continueTestsIfScrolledAsExpected(aChecker) }); else runTests(); } sendWheelAndPaint(aScrollTaget, aX, aY, aEvent, ()=>{ // sendWheelAndPaint may wait not enough for <scrollbox>. // Let's check the position before using is() for avoiding random orange. // So, this test may detect regressions with timeout. continueTestsIfScrolledAsExpected(aChecker); }); } function* testRichListbox(id) { var listbox = document.getElementById(id); function* helper(aStart, aDelta, aIntDelta, aDeltaMode) { listbox.ensureElementIsVisible(listbox.getItemAtIndex(aStart),true); let event = { deltaMode: aDeltaMode, deltaY: aDelta, lineOrPageDeltaY: aIntDelta }; // We don't need to wait for finishing the scroll in this test. yield sendWheelAndWait(listbox, 10, 10, event, ()=>{ return true; }); var change = listbox.getIndexOfFirstVisibleRow() - aStart; var direction = (change > 0) - (change < 0); var expected = (aDelta > 0) - (aDelta < 0); is(direction, expected, "testRichListbox(" + id + "): vertical, starting " + aStart + " delta " + aDelta + " lineOrPageDeltaY " + aIntDelta + " aDeltaMode " + aDeltaMode); // Check that horizontal scrolling has no effect event = { deltaMode: aDeltaMode, deltaX: aDelta, lineOrPageDeltaX: aIntDelta }; listbox.ensureElementIsVisible(listbox.getItemAtIndex(aStart),true); yield sendWheelAndWait(listbox, 10, 10, event, ()=>{ return true; }); is(listbox.getIndexOfFirstVisibleRow(), aStart, "testRichListbox(" + id + "): horizontal, starting " + aStart + " delta " + aDelta + " lineOrPageDeltaX " + aIntDelta + " aDeltaMode " + aDeltaMode); } // richlistbox currently uses native XUL scrolling, so the "line" // amounts don't necessarily correspond 1-to-1 with listbox items. So // we just check that scrolling up/down scrolls in the right direction. for (let i = 0; i < deltaModes.length; i++) { let delta = (deltaModes[i] == WheelEvent.DOM_DELTA_PIXEL) ? 32.0 : 2.0; yield* helper(5, -delta, -1, deltaModes[i]); yield* helper(5, -delta, 0, deltaModes[i]); yield* helper(5, delta, 1, deltaModes[i]); yield* helper(5, delta, 0, deltaModes[i]); } } function* testArrowScrollbox(id) { var arrowscrollbox = document.getElementById(id); var scrollbox = arrowscrollbox.scrollbox; var orient = scrollbox.getAttribute("orient"); var orientIsHorizontal = (orient == "horizontal"); function* helper(aStart, aDelta, aDeltaMode, aExpected) { var lineOrPageDelta = (aDeltaMode == WheelEvent.DOM_DELTA_PIXEL) ? aDelta / 10 : aDelta; scrollbox.scrollTo(aStart, aStart); for (let i = orientIsHorizontal ? 2 : 0; i >= 0; i--) { // Note, vertical mouse scrolling is allowed to scroll horizontal // arrowscrollboxes, because many users have no horizontal mouse scroll // capability let expected = !i ? aExpected : aStart; let getPos = ()=>{ return orientIsHorizontal ? scrollbox.scrollLeft : scrollbox.scrollTop; }; let oldPos = -1; let retry = 0; yield sendWheelAndWait(scrollbox, 5, 5, { deltaMode: aDeltaMode, deltaY: aDelta, lineOrPageDeltaY: lineOrPageDelta }, ()=>{ if (getPos() == expected) { return true; } if (oldPos == getPos()) { // If scroll stopped completely, let's continue the test. return ++retry == MAX_RETRY_COUNT; } oldPos = getPos(); retry = 0; return false; }); is(getPos(), expected, "testArrowScrollbox(" + id + "): vertical, starting " + aStart + " delta " + aDelta + " lineOrPageDelta " + lineOrPageDelta + " aDeltaMode " + aDeltaMode); } scrollbox.scrollTo(aStart, aStart); for (let i = orientIsHorizontal ? 2 : 0; i >= 0; i--) { // horizontal mouse scrolling is never allowed to scroll vertical // arrowscrollboxes let expected = (!i && orientIsHorizontal) ? aExpected : aStart; let getPos = ()=>{ return orientIsHorizontal ? scrollbox.scrollLeft : scrollbox.scrollTop; }; let oldPos = -1; let retry = 0; yield sendWheelAndWait(scrollbox, 5, 5, { deltaMode: aDeltaMode, deltaX: aDelta, lineOrPageDeltaX: lineOrPageDelta }, ()=>{ if (getPos() == expected) { return true; } if (oldPos == getPos()) { // If scroll stopped completely, let's continue the test. return ++retry == MAX_RETRY_COUNT; } oldPos = getPos(); retry = 0; return false; }); is(getPos(), expected, "testArrowScrollbox(" + id + "): horizontal, starting " + aStart + " delta " + aDelta + " lineOrPageDelta " + lineOrPageDelta + " aDeltaMode " + aDeltaMode); } } var line = arrowscrollbox.lineScrollAmount; var scrolledWidth = scrollbox.scrollWidth; var scrolledHeight = scrollbox.scrollHeight; var scrollMaxX = scrolledWidth - scrollbox.getBoundingClientRect().width; var scrollMaxY = scrolledHeight - scrollbox.getBoundingClientRect().height; var scrollMax = orientIsHorizontal ? scrollMaxX : scrollMaxY; for (let deltaMode of deltaModes) { const start = 50; const delta = 1000; let expectedNegative = 0; let expectedPositive = scrollMax; if (deltaMode == WheelEvent.DOM_DELTA_LINE) { let maxDelta = Math.floor(Math.max(1, arrowscrollbox.scrollClientSize / line)) * line; expectedNegative = Math.max(0, start - maxDelta); expectedPositive = Math.min(scrollMax, start + maxDelta); } yield* helper(start, -delta, deltaMode, expectedNegative); yield* helper(start, delta, deltaMode, expectedPositive); } } var gTestContinuation = null; function runTests() { if (!gTestContinuation) { gTestContinuation = testBody(); } var ret = gTestContinuation.next(); if (ret.done) { var winUtils = SpecialPowers.getDOMWindowUtils(window); winUtils.restoreNormalRefresh(); SimpleTest.finish(); } } async function prepareRunningTests() { // Before actually running tests, we disable auto-dir scrolling, becasue the // horizontal scrolling tests in this file are mostly meant to ensure that the // tested controls in the default style should only have one scrollbar and it // must always be in the block-flow direction so they are not really meant to // test default actions for wheel events, so we simply disabled auto-dir // scrolling, which are well tested in // dom/events/test/window_wheel_default_action.html. await SpecialPowers.pushPrefEnv({"set": [["mousewheel.autodir.enabled", false]]}); runTests(); } function* testBody() { yield* testRichListbox("richlistbox"); // Perform a mousedown to ensure the wheel transaction from the previous test // does not impact the next test. synthesizeMouse(document.scrollingElement, 0, 0, {type: "mousedown"}, window); yield* testArrowScrollbox("hscrollbox"); synthesizeMouse(document.scrollingElement, -1, -1, {type: "mousedown"}, window); yield* testArrowScrollbox("vscrollbox"); } ]]></script> </window>