author | Joel Maher <jmaher@mozilla.com> |
Wed, 14 Dec 2016 10:59:43 -0500 | |
changeset 373165 | 8fcd8f50264be9c64aa85ac39097808f5bd59b30 |
parent 373164 | 9a2a507e5b17b8bbb2360196a69df59fedc4e535 |
child 373166 | 38470e52b9d3beb7f648d8726d0c731684ddb75c |
push id | 1419 |
push user | jlund@mozilla.com |
push date | Mon, 10 Apr 2017 20:44:07 +0000 |
treeherder | mozilla-release@5e6801b73ef6 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 1272834 |
milestone | 53.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/base/content/test/general/browser_selectpopup.js +++ b/browser/base/content/test/general/browser_selectpopup.js @@ -59,29 +59,23 @@ const PAGECONTENT_SOMEHIDDEN = const PAGECONTENT_TRANSLATED = "<html><body>" + "<div id='div'>" + "<iframe id='frame' width='320' height='295' style='border: none;'" + " src='data:text/html,<select id=select autofocus><option>he he he</option><option>boo boo</option><option>baz baz</option></select>'" + "</iframe>" + "</div></body></html>"; -function openSelectPopup(selectPopup, mode = "key", selector = "select", win = window) +function openSelectPopup(selectPopup, withMouse, selector = "select", win = window) { let popupShownPromise = BrowserTestUtils.waitForEvent(selectPopup, "popupshown"); - if (mode == "click" || mode == "mousedown") { - let mousePromise; - if (mode == "click") { - mousePromise = BrowserTestUtils.synthesizeMouseAtCenter(selector, { }, win.gBrowser.selectedBrowser); - } else { - mousePromise = BrowserTestUtils.synthesizeMouse(selector, 5, 5, { type: "mousedown" }, win.gBrowser.selectedBrowser); - } - - return Promise.all([popupShownPromise, mousePromise]); + if (withMouse) { + return Promise.all([popupShownPromise, + BrowserTestUtils.synthesizeMouseAtCenter(selector, { }, win.gBrowser.selectedBrowser)]); } EventUtils.synthesizeKey("KEY_ArrowDown", { altKey: true, code: "ArrowDown" }, win); return popupShownPromise; } function hideSelectPopup(selectPopup, mode = "enter", win = window) { @@ -174,26 +168,26 @@ function* doSelectTests(contentType, dtd yield hideSelectPopup(selectPopup); is(menulist.selectedIndex, 3, "Item 3 still selected"); is((yield getInputEvents()), 1, "After closed - number of input events"); is((yield getChangeEvents()), 1, "After closed - number of change events"); // Opening and closing the popup without changing the value should not fire a change event. - yield openSelectPopup(selectPopup, "click"); + yield openSelectPopup(selectPopup, true); yield hideSelectPopup(selectPopup, "escape"); is((yield getInputEvents()), 1, "Open and close with no change - number of input events"); is((yield getChangeEvents()), 1, "Open and close with no change - number of change events"); EventUtils.synthesizeKey("VK_TAB", { }); EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }); is((yield getInputEvents()), 1, "Tab away from select with no change - number of input events"); is((yield getChangeEvents()), 1, "Tab away from select with no change - number of change events"); - yield openSelectPopup(selectPopup, "click"); + yield openSelectPopup(selectPopup, true); EventUtils.synthesizeKey("KEY_ArrowDown", { code: "ArrowDown" }); yield hideSelectPopup(selectPopup, "escape"); is((yield getInputEvents()), isWindows ? 2 : 1, "Open and close with change - number of input events"); is((yield getChangeEvents()), isWindows ? 2 : 1, "Open and close with change - number of change events"); EventUtils.synthesizeKey("VK_TAB", { }); EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }); is((yield getInputEvents()), isWindows ? 2 : 1, "Tab away from select with change - number of input events"); is((yield getChangeEvents()), isWindows ? 2 : 1, "Tab away from select with change - number of change events"); @@ -217,42 +211,42 @@ add_task(function*() { add_task(function*() { const pageUrl = "data:text/html," + escape(PAGECONTENT_SMALL); let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl); let menulist = document.getElementById("ContentSelectDropdown"); let selectPopup = menulist.menupopup; // First, try it when a different <select> element than the one that is open is removed - yield openSelectPopup(selectPopup, "click", "#one"); + yield openSelectPopup(selectPopup, true, "#one"); yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function() { content.document.body.removeChild(content.document.getElementById("two")); }); // Wait a bit just to make sure the popup won't close. yield new Promise(resolve => setTimeout(resolve, 1000)); is(selectPopup.state, "open", "Different popup did not affect open popup"); yield hideSelectPopup(selectPopup); // Next, try it when the same <select> element than the one that is open is removed - yield openSelectPopup(selectPopup, "click", "#three"); + yield openSelectPopup(selectPopup, true, "#three"); let popupHiddenPromise = BrowserTestUtils.waitForEvent(selectPopup, "popuphidden"); yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function() { content.document.body.removeChild(content.document.getElementById("three")); }); yield popupHiddenPromise; ok(true, "Popup hidden when select is removed"); // Finally, try it when the tab is closed while the select popup is open. - yield openSelectPopup(selectPopup, "click", "#one"); + yield openSelectPopup(selectPopup, true, "#one"); popupHiddenPromise = BrowserTestUtils.waitForEvent(selectPopup, "popuphidden"); yield BrowserTestUtils.removeTab(tab); yield popupHiddenPromise; ok(true, "Popup hidden when tab is closed"); }); @@ -260,17 +254,17 @@ add_task(function*() { add_task(function*() { const pageUrl = "data:text/html," + escape(PAGECONTENT_TRANSLATED); let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl); let menulist = document.getElementById("ContentSelectDropdown"); let selectPopup = menulist.menupopup; // First, get the position of the select popup when no translations have been applied. - yield openSelectPopup(selectPopup); + yield openSelectPopup(selectPopup, false); let rect = selectPopup.getBoundingClientRect(); let expectedX = rect.left; let expectedY = rect.top; yield hideSelectPopup(selectPopup); // Iterate through a set of steps which each add more translation to the select's expected position. @@ -301,17 +295,17 @@ add_task(function*() { changedWin.removeEventListener("MozAfterPaint", onPaint); resolve(); }); elem.style = contentStep[1]; }); }); - yield openSelectPopup(selectPopup); + yield openSelectPopup(selectPopup, false); expectedX += step[2]; expectedY += step[3]; let popupRect = selectPopup.getBoundingClientRect(); is(popupRect.left, expectedX, "step " + (stepIndex + 1) + " x"); is(popupRect.top, expectedY, "step " + (stepIndex + 1) + " y"); @@ -372,17 +366,17 @@ add_task(function* test_event_order() { type: "click", cancelable: true, targetIsOption: true, }, ]; for (let mode of ["enter", "click"]) { let expected = mode == "enter" ? expectedEnter : expectedClick; - yield openSelectPopup(selectPopup, "click", mode == "enter" ? "#one" : "#two"); + yield openSelectPopup(selectPopup, true, mode == "enter" ? "#one" : "#two"); let eventsPromise = ContentTask.spawn(browser, [mode, expected], function*([contentMode, contentExpected]) { return new Promise((resolve) => { function onEvent(event) { select.removeEventListener(event.type, onEvent); Assert.ok(contentExpected.length, "Unexpected event " + event.type); let expectation = contentExpected.shift(); Assert.equal(event.type, expectation.type, @@ -425,57 +419,25 @@ function* performLargePopupTests(win) select.options[60].selected = true; select.focus(); }); let selectPopup = win.document.getElementById("ContentSelectDropdown").menupopup; let browserRect = browser.getBoundingClientRect(); - // Check if a drag-select works and scrolls the list. - yield openSelectPopup(selectPopup, "mousedown", "select", win); - - let scrollPos = selectPopup.scrollBox.scrollTop; - let popupRect = selectPopup.getBoundingClientRect(); - - // First, check that scrolling does not occur when the mouse is moved over the - // anchor button but not the popup yet. - EventUtils.synthesizeMouseAtPoint(popupRect.left + 5, popupRect.top - 10, { type: "mousemove" }, win); - is(selectPopup.scrollBox.scrollTop, scrollPos, "scroll position after mousemove over button"); - - EventUtils.synthesizeMouseAtPoint(popupRect.left + 20, popupRect.top + 10, { type: "mousemove" }, win); - - // Dragging above the popup scrolls it up. - EventUtils.synthesizeMouseAtPoint(popupRect.left + 20, popupRect.top - 20, { type: "mousemove" }, win); - ok(selectPopup.scrollBox.scrollTop < scrollPos - 5, "scroll position at drag up"); - - // Dragging below the popup scrolls it down. - scrollPos = selectPopup.scrollBox.scrollTop; - EventUtils.synthesizeMouseAtPoint(popupRect.left + 20, popupRect.bottom + 20, { type: "mousemove" }, win); - ok(selectPopup.scrollBox.scrollTop > scrollPos + 5, "scroll position at drag down"); - - // Releasing the mouse button and moving the mouse does not change the scroll position. - scrollPos = selectPopup.scrollBox.scrollTop; - EventUtils.synthesizeMouseAtPoint(popupRect.left + 20, popupRect.bottom + 25, { type: "mouseup" }, win); - is(selectPopup.scrollBox.scrollTop, scrollPos, "scroll position at mouseup"); - - EventUtils.synthesizeMouseAtPoint(popupRect.left + 20, popupRect.bottom + 20, { type: "mousemove" }, win); - is(selectPopup.scrollBox.scrollTop, scrollPos, "scroll position at mouseup again"); - - yield hideSelectPopup(selectPopup, "escape", win); - let positions = [ "margin-top: 300px;", "position: fixed; bottom: 100px;", "width: 100%; height: 9999px;" ]; let position; - while (positions.length) { - yield openSelectPopup(selectPopup, "key", "select", win); + while (true) { + yield openSelectPopup(selectPopup, false, "select", win); let rect = selectPopup.getBoundingClientRect(); ok(rect.top >= browserRect.top, "Popup top position in within browser area"); ok(rect.bottom <= browserRect.bottom, "Popup bottom position in within browser area"); // Don't check the scroll position for the last step as the popup will be cut off. if (positions.length > 0) { let cs = win.getComputedStyle(selectPopup); @@ -484,21 +446,24 @@ function* performLargePopupTests(win) is(selectPopup.childNodes[60].getBoundingClientRect().bottom, selectPopup.getBoundingClientRect().bottom - bpBottom, "Popup scroll at correct position " + bpBottom); } yield hideSelectPopup(selectPopup, "enter", win); position = positions.shift(); + if (!position) { + break; + } let contentPainted = BrowserTestUtils.contentPainted(browser); yield ContentTask.spawn(browser, position, function*(contentPosition) { let select = content.document.getElementById("one"); - select.setAttribute("style", contentPosition || ""); + select.setAttribute("style", contentPosition); }); yield contentPainted; } } // This test checks select elements with a large number of options to ensure that // the popup appears within the browser area. add_task(function* test_large_popup() { @@ -549,17 +514,17 @@ add_task(function* test_mousemove_correc }); yield BrowserTestUtils.synthesizeMouseAtCenter("#one", { type: "mouseup" }, gBrowser.selectedBrowser); yield hideSelectPopup(selectPopup); // The popup should be closed when fullscreen mode is entered or exited. for (let steps = 0; steps < 2; steps++) { - yield openSelectPopup(selectPopup, "click"); + yield openSelectPopup(selectPopup, true); let popupHiddenPromise = BrowserTestUtils.waitForEvent(selectPopup, "popuphidden"); let sizeModeChanged = BrowserTestUtils.waitForEvent(window, "sizemodechange"); BrowserFullScreen(); yield sizeModeChanged; yield popupHiddenPromise; } yield BrowserTestUtils.removeTab(tab);
--- a/toolkit/content/widgets/popup.xml +++ b/toolkit/content/widgets/popup.xml @@ -241,22 +241,16 @@ <content> <xul:arrowscrollbox class="popup-internal-box" flex="1" orient="vertical" smoothscroll="false"> <children/> </xul:arrowscrollbox> </content> - <implementation> - <field name="scrollBox" readonly="true"> - document.getAnonymousElementByAttribute(this, "class", "popup-internal-box"); - </field> - </implementation> - <handlers> <handler event="popupshowing" phase="target"> <![CDATA[ var array = []; var width = 0; for (var menuitem = this.firstChild; menuitem; menuitem = menuitem.nextSibling) { if (menuitem.localName == "menuitem" && menuitem.hasAttribute("acceltext")) { var accel = document.getAnonymousElementByAttribute(menuitem, "anonid", "accel"); @@ -627,15 +621,15 @@ this._isMouseOver = false; this._mouseOutCount = 0; ]]></handler> </handlers> </binding> <binding id="popup-scrollbars" extends="chrome://global/content/bindings/popup.xml#popup"> <content> - <xul:scrollbox class="popup-internal-box" flex="1" orient="vertical" style="overflow: auto;"> + <xul:hbox class="popup-internal-box" flex="1" orient="vertical" style="overflow: auto;"> <children/> - </xul:scrollbox> + </xul:hbox> </content> </binding> </bindings>
--- a/toolkit/content/widgets/scrollbox.xml +++ b/toolkit/content/widgets/scrollbox.xml @@ -16,25 +16,16 @@ </binding> <binding id="scrollbox" extends="chrome://global/content/bindings/scrollbox.xml#scrollbox-base"> <content> <xul:box class="box-inherit scrollbox-innerbox" xbl:inherits="orient,align,pack,dir" flex="1"> <children/> </xul:box> </content> - - <implementation> - <method name="scrollByIndex"> - <parameter name="index"/> - <body> - this.boxObject.scrollByIndex(index); - </body> - </method> - </implementation> </binding> <binding id="arrowscrollbox" extends="chrome://global/content/bindings/scrollbox.xml#scrollbox-base"> <content> <xul:autorepeatbutton class="autorepeatbutton-up" anonid="scrollbutton-up" xbl:inherits="orient,collapsed=notoverflowing,disabled=scrolledtostart" oncommand="_autorepeatbuttonScroll(event);"/>
--- a/toolkit/modules/SelectParentHelper.jsm +++ b/toolkit/modules/SelectParentHelper.jsm @@ -9,28 +9,22 @@ this.EXPORTED_SYMBOLS = [ ]; const {utils: Cu} = Components; const {AppConstants} = Cu.import("resource://gre/modules/AppConstants.jsm"); // Maximum number of rows to display in the select dropdown. const MAX_ROWS = 20; -// Interval between autoscrolls -const AUTOSCROLL_INTERVAL = 25; - var currentBrowser = null; var currentMenulist = null; var currentZoom = 1; var closedWithEnter = false; this.SelectParentHelper = { - draggedOverPopup: false, - scrollTimer: 0, - populate: function(menulist, items, selectedIndex, zoom) { // Clear the current contents of the popup menulist.menupopup.textContent = ""; currentZoom = zoom; currentMenulist = menulist; populateChildren(menulist, items, selectedIndex, zoom); }, @@ -62,85 +56,38 @@ this.SelectParentHelper = { menupopup.classList.toggle("isOpenedViaTouch", isOpenedViaTouch); let constraintRect = browser.getBoundingClientRect(); constraintRect = new win.DOMRect(constraintRect.left + win.mozInnerScreenX, constraintRect.top + win.mozInnerScreenY, constraintRect.width, constraintRect.height); menupopup.setConstraintRect(constraintRect); menupopup.openPopupAtScreenRect(AppConstants.platform == "macosx" ? "selection" : "after_start", rect.left, rect.top, rect.width, rect.height, false, false); - - // Set up for dragging - menupopup.setCaptureAlways(); - this.draggedOverPopup = false; - menupopup.addEventListener("mousemove", this); }, hide: function(menulist, browser) { if (currentBrowser == browser) { menulist.menupopup.hidePopup(); } }, - clearScrollTimer: function() { - if (this.scrollTimer) { - let win = currentBrowser.ownerDocument.defaultView; - win.clearInterval(this.scrollTimer); - this.scrollTimer = 0; - } - }, - handleEvent: function(event) { switch (event.type) { case "mouseup": - this.clearScrollTimer(); - currentMenulist.menupopup.removeEventListener("mousemove", this); currentBrowser.messageManager.sendAsyncMessage("Forms:MouseUp", {}); break; case "mouseover": currentBrowser.messageManager.sendAsyncMessage("Forms:MouseOver", {}); break; case "mouseout": currentBrowser.messageManager.sendAsyncMessage("Forms:MouseOut", {}); break; - case "mousemove": - let menupopup = currentMenulist.menupopup; - let popupRect = menupopup.getOuterScreenRect(); - - this.clearScrollTimer(); - - // If dragging outside the top or bottom edge of the popup, but within - // the popup area horizontally, scroll the list in that direction. The - // draggedOverPopup flag is used to ensure that scrolling does not start - // until the mouse has moved over the popup first, preventing scrolling - // while over the dropdown button. - if (event.screenX >= popupRect.left && event.screenX <= popupRect.right) { - if (!this.draggedOverPopup) { - if (event.screenY > popupRect.top && event.screenY < popupRect.bottom) { - this.draggedOverPopup = true; - } - } - - if (this.draggedOverPopup && - (event.screenY <= popupRect.top || event.screenY >= popupRect.bottom)) { - let scrollAmount = event.screenY <= popupRect.top ? -1 : 1; - menupopup.scrollBox.scrollByIndex(scrollAmount); - - let win = currentBrowser.ownerDocument.defaultView; - this.scrollTimer = win.setInterval(function() { - menupopup.scrollBox.scrollByIndex(scrollAmount); - }, AUTOSCROLL_INTERVAL); - } - } - - break; - case "keydown": if (event.keyCode == event.DOM_VK_RETURN) { closedWithEnter = true; } break; case "command": if (event.target.hasAttribute("value")) { @@ -156,18 +103,16 @@ this.SelectParentHelper = { currentMenulist.menupopup.hidePopup(); } break; case "popuphidden": currentBrowser.messageManager.sendAsyncMessage("Forms:DismissedDropDown", {}); let popup = event.target; this._unregisterListeners(currentBrowser, popup); - this.clearScrollTimer(); - popup.releaseCapture(); popup.parentNode.hidden = true; currentBrowser = null; currentMenulist = null; currentZoom = 1; break; } },