Backed out 7 changesets (bug 1519577) for mochitest failures. CLOSED TREE

Backed out changeset 5192370c4f79 (bug 1519577)
Backed out changeset 2999bbc0422b (bug 1519577)
Backed out changeset bcedf1e9b09c (bug 1519577)
Backed out changeset 293af339be51 (bug 1519577)
Backed out changeset 9f311461ad1e (bug 1519577)
Backed out changeset cf4e91d423b4 (bug 1519577)
Backed out changeset 4f53ad1e3674 (bug 1519577)
This commit is contained in:
Cosmin Sabou 2019-05-22 02:20:08 +03:00
parent bdf1d2a559
commit ce81aa750c
44 changed files with 439 additions and 264 deletions

View File

@ -239,9 +239,6 @@ var BrowserPageActions = {
"subviewbutton-iconic",
"pageAction-panel-button"
);
if (action.isBadged) {
buttonNode.setAttribute("badged", "true");
}
buttonNode.setAttribute("actionid", action.id);
buttonNode.addEventListener("command", event => {
this.doCommandForAction(action, event, buttonNode);
@ -1129,6 +1126,7 @@ BrowserPageActions.addSearchEngine = {
this._updateTitleAndIcon();
this.action.setWantsSubview(this.engines.length > 1, window);
let button = BrowserPageActions.panelButtonNodeForActionID(this.action.id);
button.classList.add("badged-button");
button.setAttribute("image", this.engines[0].icon);
button.setAttribute("uri", this.engines[0].uri);
button.setAttribute("crop", "center");
@ -1141,7 +1139,7 @@ BrowserPageActions.addSearchEngine = {
}
for (let engine of this.engines) {
let button = document.createXULElement("toolbarbutton");
button.classList.add("subviewbutton", "subviewbutton-iconic", "badged-button");
button.classList.add("subviewbutton", "subviewbutton-iconic");
button.setAttribute("label", engine.title);
button.setAttribute("image", engine.icon);
button.setAttribute("uri", engine.uri);

View File

@ -1136,7 +1136,8 @@ var LibraryUI = {
let animatableBox = document.getElementById("library-animatable-box");
let navBar = document.getElementById("nav-bar");
let iconBounds = window.windowUtils.getBoundsWithoutFlushing(libraryButton.icon);
let libraryIcon = document.getAnonymousElementByAttribute(libraryButton, "class", "toolbarbutton-icon");
let iconBounds = window.windowUtils.getBoundsWithoutFlushing(libraryIcon);
let libraryBounds = window.windowUtils.getBoundsWithoutFlushing(libraryButton);
animatableBox.style.setProperty("--library-button-height", libraryBounds.height + "px");
@ -1196,7 +1197,8 @@ var LibraryUI = {
}
let animatableBox = document.getElementById("library-animatable-box");
let iconBounds = window.windowUtils.getBoundsWithoutFlushing(libraryButton.icon);
let libraryIcon = document.getAnonymousElementByAttribute(libraryButton, "class", "toolbarbutton-icon");
let iconBounds = window.windowUtils.getBoundsWithoutFlushing(libraryIcon);
// Resizing the window will only have the ability to change the X offset of the
// library button.

View File

@ -568,7 +568,7 @@ function UpdateBackForwardCommands(aWebNavigation) {
/**
* Click-and-Hold implementation for the Back and Forward buttons
* XXXmano: should this live in toolbarbutton.js?
* XXXmano: should this live in toolbarbutton.xml?
*/
function SetClickAndHoldHandlers() {
// Bug 414797: Clone the back/forward buttons' context menu into both buttons.
@ -579,13 +579,13 @@ function SetClickAndHoldHandlers() {
let backButton = document.getElementById("back-button");
backButton.setAttribute("type", "menu");
backButton.prepend(popup);
backButton.appendChild(popup);
gClickAndHoldListenersOnElement.add(backButton);
let forwardButton = document.getElementById("forward-button");
popup = popup.cloneNode(true);
forwardButton.setAttribute("type", "menu");
forwardButton.prepend(popup);
forwardButton.appendChild(popup);
gClickAndHoldListenersOnElement.add(forwardButton);
}
@ -600,7 +600,7 @@ const gClickAndHoldListenersOnElement = {
return;
// Prevent the menupopup from opening immediately
aEvent.currentTarget.menupopup.hidden = true;
aEvent.currentTarget.firstElementChild.hidden = true;
aEvent.currentTarget.addEventListener("mouseout", this);
aEvent.currentTarget.addEventListener("mouseup", this);
@ -8423,7 +8423,8 @@ var PanicButtonNotifier = {
popup.addEventListener("popuphidden", removeListeners);
let widget = CustomizableUI.getWidget("panic-button").forWindow(window);
let anchor = widget.anchor.icon;
let anchor = widget.anchor;
anchor = document.getAnonymousElementByAttribute(anchor, "class", "toolbarbutton-icon");
popup.openPopup(anchor, popup.getAttribute("position"));
} catch (ex) {
Cu.reportError(ex);

View File

@ -745,8 +745,7 @@
removable="true"/>
<toolbarbutton id="alltabs-button"
class="toolbarbutton-1 chromeclass-toolbar-additional tabs-alltabs-button"
badged="true"
class="toolbarbutton-1 chromeclass-toolbar-additional tabs-alltabs-button badged-button"
oncommand="gTabsPanel.showAllTabsPanel();"
label="&listAllTabs.label;"
tooltiptext="&listAllTabs.label;"
@ -1022,8 +1021,7 @@
during the customization of the toolbar, in the palette, and before
the Downloads Indicator overlay is loaded. -->
<toolbarbutton id="downloads-button"
class="toolbarbutton-1 chromeclass-toolbar-additional"
badged="true"
class="toolbarbutton-1 chromeclass-toolbar-additional badged-button"
key="key_openDownloads"
onmousedown="DownloadsIndicatorView.onCommand(event);"
onkeypress="DownloadsIndicatorView.onCommand(event);"
@ -1059,8 +1057,7 @@
tooltiptext="&libraryButton.tooltip;"
label="&places.library.title;"/>
<toolbarbutton id="fxa-toolbar-menu-button" class="toolbarbutton-1 chromeclass-toolbar-additional subviewbutton-nav"
badged="true"
<toolbarbutton id="fxa-toolbar-menu-button" class="toolbarbutton-1 badged-button chromeclass-toolbar-additional subviewbutton-nav"
onmousedown="gSync.toggleAccountPanel('PanelUI-fxa', event)"
onkeypress="gSync.toggleAccountPanel('PanelUI-fxa', event)"
consumeanchor="fxa-toolbar-menu-button"
@ -1087,8 +1084,7 @@
<toolbaritem id="PanelUI-button"
removable="false">
<toolbarbutton id="PanelUI-menu-button"
class="toolbarbutton-1"
badged="true"
class="toolbarbutton-1 badged-button"
consumeanchor="PanelUI-button"
label="&brandShortName;"
tooltiptext="&appmenu.tooltip;"/>
@ -1207,6 +1203,7 @@
type="menu"
label="&bookmarksMenuButton2.label;"
tooltip="dynamic-shortcut-tooltip"
anchor="dropmarker"
ondragenter="PlacesMenuDNDHandler.onDragEnter(event);"
ondragover="PlacesMenuDNDHandler.onDragOver(event);"
ondragleave="PlacesMenuDNDHandler.onDragLeave(event);"

View File

@ -210,9 +210,6 @@
containersEnabled = false;
}
// There are separate "new tab" buttons for when the tab strip
// is overflowed and when it is not. Attach the long click
// popup to both of them.
const newTab = document.getElementById("new-tab-button");
const newTab2 = document.getAnonymousElementByAttribute(this, "anonid", "tabs-newtab-button");
@ -222,8 +219,8 @@
gClickAndHoldListenersOnElement.remove(parent);
parent.removeAttribute("type");
if (parent.menupopup) {
parent.menupopup.remove();
if (parent.firstElementChild) {
parent.firstElementChild.remove();
}
if (containersEnabled) {
@ -243,7 +240,7 @@
showDefaultTab: Services.prefs.getIntPref("privacy.userContext.longPressBehavior") == 1,
});
});
parent.prepend(popup);
parent.appendChild(popup);
// longPressBehavior == 2 means that the menu is shown after X
// millisecs. Otherwise, with 1, the menu is open immediatelly.

View File

@ -167,7 +167,8 @@ async function test_playing_icon_on_hidden_tab(tab) {
];
let tabContainer = tab.parentNode;
let alltabsButton = document.getElementById("alltabs-button");
let alltabsBadge = alltabsButton.badgeLabel;
let alltabsBadge = document.getAnonymousElementByAttribute(
alltabsButton, "class", "toolbarbutton-badge");
function assertIconShowing() {
is(getComputedStyle(alltabsBadge).backgroundImage,

View File

@ -4438,7 +4438,7 @@ OverflowableToolbar.prototype = {
let mainView = doc.getElementById(mainViewId);
let contextMenu = doc.getElementById(mainView.getAttribute("context"));
gELS.addSystemEventListener(contextMenu, "command", this, true);
let anchor = this._chevron.icon;
let anchor = doc.getAnonymousElementByAttribute(this._chevron, "class", "toolbarbutton-icon");
// Ensure we update the gEditUIVisible flag when opening the popup, in
// case the edit controls are in it.
this._panel.addEventListener("popupshowing", () => doc.defaultView.updateEditUIVisibility(), {once: true});

View File

@ -1348,11 +1348,6 @@ var PanelView = class extends AssociatedToNode {
continue;
}
// Ignore content inside a <toolbarbutton>
if (element.tagName != "toolbarbutton" && element.closest("toolbarbutton")) {
continue;
}
// Take the label for toolbarbuttons; it only exists on those elements.
element = element.multilineLabel || element;

View File

@ -866,7 +866,11 @@ const PanelUI = {
_getBadgeStatus(notification) { return notification.id; },
_getPanelAnchor(candidate) {
let iconAnchor = candidate.badgeStack || candidate.icon;
let iconAnchor =
document.getAnonymousElementByAttribute(candidate, "class",
"toolbarbutton-badge-stack") ||
document.getAnonymousElementByAttribute(candidate, "class",
"toolbarbutton-icon");
return iconAnchor || candidate;
},

View File

@ -30,7 +30,7 @@ const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const kForceOverflowWidthPx = 300;
function createDummyXULButton(id, label, win = window) {
let btn = win.document.createElementNS(kNSXUL, "toolbarbutton");
let btn = document.createElementNS(kNSXUL, "toolbarbutton");
btn.id = id;
btn.setAttribute("label", label || id);
btn.className = "toolbarbutton-1 chromeclass-toolbar-additional";
@ -445,7 +445,8 @@ function checkContextMenu(aContextMenu, aExpectedEntries, aWindow = window) {
function waitForOverflowButtonShown(win = window) {
let ov = win.document.getElementById("nav-bar-overflow-button");
return waitForElementShown(ov.icon);
let icon = win.document.getAnonymousElementByAttribute(ov, "class", "toolbarbutton-icon");
return waitForElementShown(icon);
}
function waitForElementShown(element) {
let win = element.ownerGlobal;

View File

@ -613,10 +613,11 @@ const DownloadsIndicatorView = {
let widgetGroup = CustomizableUI.getWidget("downloads-button");
if (widgetGroup.areaType == CustomizableUI.TYPE_MENU_PANEL) {
let overflowIcon = widgetGroup.forWindow(window).anchor;
return overflowIcon.icon;
return document.getAnonymousElementByAttribute(overflowIcon, "class", "toolbarbutton-icon");
}
return this.indicator.badgeStack;
return document.getAnonymousElementByAttribute(this.indicator, "class",
"toolbarbutton-badge-stack");
},
get _progressIcon() {

View File

@ -47,7 +47,8 @@ add_task(async function test_overflow_anchor() {
EventUtils.sendMouseEvent({ type: "mousedown", button: 0 }, button.node);
await promise;
let downloadsAnchor = button.node.badgeStack;
let downloadsAnchor = document.getAnonymousElementByAttribute(button.node, "class",
"toolbarbutton-badge-stack");
is(panel.anchorNode, downloadsAnchor);
DownloadsPanel.hidePanel();

View File

@ -275,7 +275,8 @@ class ExtensionControlledPopup {
// Anchor to a toolbar browserAction if found, otherwise use the menu button.
anchorButton = action || doc.getElementById("PanelUI-menu-button");
}
let anchor = anchorButton.icon;
let anchor = doc.getAnonymousElementByAttribute(
anchorButton, "class", "toolbarbutton-icon");
panel.hidden = false;
popupnotification.show();
panel.openPopup(anchor);

View File

@ -165,8 +165,8 @@ this.browserAction = class extends ExtensionAPI {
},
onCreated: node => {
node.classList.add("badged-button");
node.classList.add("webextension-browser-action");
node.setAttribute("badged", "true");
node.setAttribute("constrain-size", "true");
node.setAttribute("data-extensionid", this.extension.id);

View File

@ -129,7 +129,8 @@ async function runTests(options) {
is(button.getAttribute("disabled") == "true", !details.enabled, "disabled state is correct");
if (details.badge) {
let badge = button.badgeLabel;
let badge = button.ownerDocument.getAnonymousElementByAttribute(
button, "class", "toolbarbutton-badge");
let style = window.getComputedStyle(badge);
let expected = {
backgroundColor: serializeColor(details.badgeBackgroundColor),
@ -425,7 +426,7 @@ add_task(async function testBadgeColorPersistence() {
function getBadgeForWindow(win) {
const widget = getBrowserActionWidget(extension).forWindow(win).node;
return widget.badgeLabel;
return document.getAnonymousElementByAttribute(widget, "class", "toolbarbutton-badge");
}
let badge = getBadgeForWindow(window);

View File

@ -247,7 +247,7 @@ add_task(async function browseraction_contextmenu_manage_extension() {
info("Wait until the overflow menu is ready");
let overflowButton = win.document.getElementById("nav-bar-overflow-button");
let icon = overflowButton.icon;
let icon = win.document.getAnonymousElementByAttribute(overflowButton, "class", "toolbarbutton-icon");
await waitForElementShown(icon);
if (!customizing) {
@ -326,7 +326,7 @@ async function runTestContextMenu({
info("Wait until the overflow menu is ready");
let overflowButton = win.document.getElementById("nav-bar-overflow-button");
let icon = overflowButton.icon;
let icon = win.document.getAnonymousElementByAttribute(overflowButton, "class", "toolbarbutton-icon");
await waitForElementShown(icon);
if (!customizing) {

View File

@ -1519,7 +1519,7 @@ PlacesToolbar.prototype = {
// If the menu is open, close it.
if (draggedElt.open) {
draggedElt.menupopup.hidePopup();
draggedElt.lastElementChild.hidePopup();
draggedElt.open = false;
}
}

View File

@ -289,7 +289,7 @@ function getNodeForToolbarItem(itemGuid, validator) {
// Don't search in queries, they could contain our item in a
// different position. Search only folders
if (PlacesUtils.nodeIsFolder(child._placesNode)) {
var popup = child.menupopup;
var popup = child.lastElementChild;
popup.openPopup();
var foundNode = findNode(popup);
popup.hidePopup();

View File

@ -37,7 +37,7 @@ add_task(async function test() {
Assert.equal(menuButton.type, "menu", "A menu button");
// Mouse over the menu button to open it.
let buttonPopup = menuButton.menupopup;
let buttonPopup = menuButton.firstElementChild;
promise = promiseEvent(buttonPopup, "popupshown");
EventUtils.synthesizeMouse(menuButton, 5, 5, { type: "mousemove" });
await promise;

View File

@ -87,7 +87,9 @@ var UITour = {
// Otherwise use the sync setup icon.
let statusButton = aDocument.getElementById("appMenu-fxa-label");
return statusButton.icon;
return aDocument.getAnonymousElementByAttribute(statusButton,
"class",
"toolbarbutton-icon");
},
// This is a fake widgetName starting with the "appMenu-" prefix so we know
// to automatically open the appMenu when annotating this target.

View File

@ -455,9 +455,6 @@ var PageActions = {
* some reason. You can also pass an object that maps pixel sizes to
* URLs, like { 16: url16, 32: url32 }. The best size for the user's
* screen will be used.
* @param isBadged (bool, optional)
* If true, the toolbarbutton for this action will get the
* "badged-button" class.
* @param onBeforePlacedInWindow (function, optional)
* Called before the action is placed in the window:
* onBeforePlacedInWindow(window)
@ -540,7 +537,6 @@ function Action(options) {
disabled: false,
extensionID: false,
iconURL: false,
isBadged: false,
labelForHistogram: false,
onBeforePlacedInWindow: false,
onCommand: false,
@ -820,10 +816,6 @@ Action.prototype = {
return this._wantsIframe || false;
},
get isBadged() {
return this._isBadged || false;
},
get labelForHistogram() {
// The histogram label value has a length limit of 20 and restricted to a
// pattern. See MAX_LABEL_LENGTH and CPP_IDENTIFIER_PATTERN in
@ -1192,7 +1184,6 @@ var gBuiltInActions = [
id: "addSearchEngine",
// The title is set in browser-pageActions.js.
title: "",
isBadged: true,
_transient: true,
onShowingInPanel(buttonNode) {
browserPageActions(buttonNode).addSearchEngine.onShowingInPanel();

View File

@ -12,14 +12,14 @@ const TEST_URL = URL_ROOT + "doc_markup_anonymous_xul.xul";
add_task(async function() {
const {inspector} = await openInspectorForURL(TEST_URL);
const boundNode = await getNodeFront("#xbl-host", inspector);
const children = await inspector.walker.children(boundNode);
const toolbarbutton = await getNodeFront("toolbarbutton", inspector);
const children = await inspector.walker.children(toolbarbutton);
is(boundNode.numChildren, 2, "Correct number of children");
is(children.nodes.length, 2, "Children returned from walker");
is(toolbarbutton.numChildren, 4, "Correct number of children");
is(children.nodes.length, 4, "Children returned from walker");
is(boundNode.isAnonymous, false, "Node with XBL binding is not anonymous");
await isEditingMenuEnabled(boundNode, inspector);
is(toolbarbutton.isAnonymous, false, "Toolbarbutton is not anonymous");
await isEditingMenuEnabled(toolbarbutton, inspector);
for (const node of children.nodes) {
ok(node.isAnonymous, "Child is anonymous");

View File

@ -3,15 +3,6 @@
<xul:window xmlns="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="Test anonymous xul nodes.">
<xbl:bindings xmlns:xbl="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gaktekeeper/there.is.only.xul">
<xbl:binding id="test">
<xbl:content>
<xul:box anonid="xbl-anon1">Anonymous</xul:box>
<xul:box anonid="xbl-anon2">Anonymous</xul:box>
</xbl:content>
</xbl:binding>
</xbl:bindings>
<box id="xbl-host" style="-moz-binding: url(#test)"/>
<xul:toolbarbutton id="test"></xul:toolbarbutton>
</xul:window>

View File

@ -4,7 +4,6 @@ support-files =
blockNoPlugins.xml
blockPluginHard.xml
bug418986-1.js
clonedoc/**
cpows_child.js
cpows_parent.xul
file_bug549682.xul

View File

@ -1 +0,0 @@
content clonedoc content/

View File

@ -1,4 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<something>
<somethinglese/>
</something>

View File

@ -17,20 +17,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=467123
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
/** Test for Bug 467123 **/
let url = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService)
.newURI(document.location.href);
let file = Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIChromeRegistry)
.convertChromeURL(url)
.QueryInterface(Ci.nsIFileURL)
.file.parent;
file.append("clonedoc");
Components.manager.addBootstrappedManifestLocation(file);
/** Test for Bug 467123 **/
var xhr = new XMLHttpRequest();
xhr.open("GET", "chrome://clonedoc/content/doc.xml", false);
xhr.open("GET", "chrome://global/content/bindings/button.xml", false);
xhr.send();
ok(xhr.responseXML, "We should have response document!");
var e = null;

View File

@ -625,6 +625,25 @@ nsresult nsMenuFrame::AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
return NS_OK;
}
nsIContent* nsMenuFrame::GetAnchor() {
mozilla::dom::Element* anchor = nullptr;
nsAutoString id;
mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::anchor, id);
if (!id.IsEmpty()) {
Document* doc = mContent->OwnerDoc();
anchor =
doc->GetAnonymousElementByAttribute(mContent, nsGkAtoms::anonid, id);
if (!anchor) {
anchor = doc->GetElementById(id);
}
}
// Always return the menu's content if the anchor wasn't set or wasn't found.
return anchor && anchor->GetPrimaryFrame() ? anchor : GetContent();
}
void nsMenuFrame::OpenMenu(bool aSelectFirstItem) {
if (!mContent) return;
@ -674,7 +693,8 @@ nsMenuFrame::DoXULLayout(nsBoxLayoutState& aState) {
nsMenuPopupFrame* popupFrame = GetPopup();
if (popupFrame) {
bool sizeToPopup = IsSizedToPopup(mContent, false);
popupFrame->LayoutPopup(aState, this, sizeToPopup);
popupFrame->LayoutPopup(aState, this, GetAnchor()->GetPrimaryFrame(),
sizeToPopup);
}
return rv;

View File

@ -123,6 +123,12 @@ class nsMenuFrame final : public nsBoxFrame, public nsIReflowCallback {
virtual nsIScrollableFrame* GetScrollTargetFrame() override;
// Retrieve the element that the menu should be anchored to. By default this
// is the menu itself. However, the anchor attribute may refer to the value of
// an anonid within the menu's binding, or, if not found, the id of an element
// in the document.
nsIContent* GetAnchor();
/**
* NOTE: OpenMenu will open the menu asynchronously.
*/

View File

@ -461,7 +461,8 @@ void nsMenuPopupFrame::UpdateWidgetProperties() {
}
void nsMenuPopupFrame::LayoutPopup(nsBoxLayoutState& aState,
nsIFrame* aParentMenu, bool aSizedToPopup) {
nsIFrame* aParentMenu, nsIFrame* aAnchor,
bool aSizedToPopup) {
if (IsLeaf()) {
return;
}
@ -516,7 +517,7 @@ void nsMenuPopupFrame::LayoutPopup(nsBoxLayoutState& aState,
bool needCallback = false;
if (shouldPosition) {
SetPopupPosition(aParentMenu, false, aSizedToPopup,
SetPopupPosition(aAnchor, false, aSizedToPopup,
mPopupState == ePopupPositioning);
needCallback = true;
}
@ -543,7 +544,7 @@ void nsMenuPopupFrame::LayoutPopup(nsBoxLayoutState& aState,
}
if (rePosition) {
SetPopupPosition(aParentMenu, false, aSizedToPopup, false);
SetPopupPosition(aAnchor, false, aSizedToPopup, false);
}
nsPresContext* pc = PresContext();
@ -603,7 +604,7 @@ void nsMenuPopupFrame::LayoutPopup(nsBoxLayoutState& aState,
if (needCallback && !mReflowCallbackData.mPosted) {
pc->PresShell()->PostReflowCallback(this);
mReflowCallbackData.MarkPosted(aParentMenu, aSizedToPopup, openChanged);
mReflowCallbackData.MarkPosted(aAnchor, aSizedToPopup, openChanged);
}
}

View File

@ -257,7 +257,7 @@ class nsMenuPopupFrame final : public nsBoxFrame,
// layout, position and display the popup as needed
MOZ_CAN_RUN_SCRIPT_BOUNDARY
void LayoutPopup(nsBoxLayoutState& aState, nsIFrame* aParentMenu,
bool aSizedToPopup);
nsIFrame* aAnchor, bool aSizedToPopup);
nsView* GetRootViewForPopup(nsIFrame* aStartFrame);

View File

@ -109,7 +109,7 @@ nsPopupSetFrame::DoXULLayout(nsBoxLayoutState& aState) {
// lay out all of our currently open popups.
for (nsFrameList::Enumerator e(mPopupList); !e.AtEnd(); e.Next()) {
nsMenuPopupFrame* popupChild = static_cast<nsMenuPopupFrame*>(e.get());
popupChild->LayoutPopup(aState, nullptr, false);
popupChild->LayoutPopup(aState, nullptr, nullptr, false);
}
return rv;

View File

@ -682,7 +682,7 @@ void nsXULPopupManager::ShowMenu(nsIContent* aMenu, bool aSelectFirstItem,
// there is no trigger event for menus
InitTriggerEvent(nullptr, nullptr, nullptr);
popupFrame->InitializePopup(aMenu, nullptr, position, 0, 0,
popupFrame->InitializePopup(menuFrame->GetAnchor(), nullptr, position, 0, 0,
MenuPopupAnchorType_Node, true);
if (aAsynchronous) {

View File

@ -32,7 +32,7 @@ add_task(async function test_button_background_properties() {
await extension.startup();
let toolbarButton = document.querySelector("#home-button");
let toolbarButtonIcon = toolbarButton.icon;
let toolbarButtonIcon = document.getAnonymousElementByAttribute(toolbarButton, "class", "toolbarbutton-icon");
let toolbarButtonIconCS = window.getComputedStyle(toolbarButtonIcon);
InspectorUtils.addPseudoClassLock(toolbarButton, ":hover");

View File

@ -659,7 +659,6 @@ if (!isDummyDocument) {
"chrome://global/content/elements/textbox.js",
"chrome://global/content/elements/tabbox.js",
"chrome://global/content/elements/text.js",
"chrome://global/content/elements/toolbarbutton.js",
"chrome://global/content/elements/tree.js",
"chrome://global/content/elements/wizard.js",
]) {

View File

@ -62,6 +62,7 @@ toolkit.jar:
#endif
content/global/widgets.css
content/global/bindings/autocomplete.xml (widgets/autocomplete.xml)
content/global/bindings/button.xml (widgets/button.xml)
content/global/bindings/calendar.js (widgets/calendar.js)
content/global/bindings/datekeeper.js (widgets/datekeeper.js)
content/global/bindings/datepicker.js (widgets/datepicker.js)
@ -76,6 +77,7 @@ toolkit.jar:
* content/global/bindings/textbox.xml (widgets/textbox.xml)
content/global/bindings/timekeeper.js (widgets/timekeeper.js)
content/global/bindings/timepicker.js (widgets/timepicker.js)
content/global/bindings/toolbarbutton.xml (widgets/toolbarbutton.xml)
content/global/bindings/wizard.xml (widgets/wizard.xml)
content/global/elements/autocomplete-popup.js (widgets/autocomplete-popup.js)
content/global/elements/autocomplete-richlistitem.js (widgets/autocomplete-richlistitem.js)
@ -101,7 +103,6 @@ toolkit.jar:
content/global/elements/tabbox.js (widgets/tabbox.js)
content/global/elements/text.js (widgets/text.js)
content/global/elements/textbox.js (widgets/textbox.js)
content/global/elements/toolbarbutton.js (widgets/toolbarbutton.js)
content/global/elements/videocontrols.js (widgets/videocontrols.js)
content/global/elements/tree.js (widgets/tree.js)
content/global/elements/wizard.js (widgets/wizard.js)

View File

@ -127,6 +127,7 @@ support-files = window_maximized_persist.xul
[test_navigate_persist.html]
support-files = window_navigate_persist.html
[test_menu.xul]
[test_menu_anchored.xul]
[test_menu_withcapture.xul]
[test_menu_hide.xul]
[test_menuchecks.xul]

View File

@ -9,14 +9,22 @@
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<toolbarbutton type="menu" id="toolbarmenu" height="200">
<xbl:bindings xmlns:xbl="http://www.mozilla.org/xbl">
<xbl:binding id="menu" extends="chrome://global/content/bindings/button.xml#button-base">
<xbl:content>
<xbl:children includes="menupopup"/>
<xul:stack>
<xul:button width="100" left="0" top="0" height="30" allowevents="true"
onclick="eventReceived('clickbutton1'); return false;"/>
<xul:button width="100" left="70" top="0" height="30"
onclick="eventReceived('clickbutton2'); return false;"/>
</xul:stack>
</xbl:content>
</xbl:binding>
</xbl:bindings>
<toolbarbutton type="menu" id="toolbarmenu" height="200" style="-moz-binding: url(#menu);">
<menupopup id="menupopup" onpopupshowing="eventReceived('popupshowing'); return false;"/>
<stack>
<button width="100" left="0" top="0" height="30" allowevents="true"
onclick="eventReceived('clickbutton1'); return false;"/>
<button width="100" left="70" top="0" height="30"
onclick="eventReceived('clickbutton2'); return false;"/>
</stack>
</toolbarbutton>
<!-- test results are displayed in the html:body -->

View File

@ -0,0 +1,77 @@
<?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"?>
<!--
Test for menus with the anchor attribute set
-->
<window title="Anchored Menus Test"
align="start"
onload="setTimeout(runTest, 0, 'tb1');"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript" src="xul_selectcontrol.js"/>
<hbox>
<toolbarbutton id="tb1" type="menu" label="Open" anchor="dropmarker">
<menupopup id="popup1"
onpopupshown="checkPopup(this, document.getAnonymousElementByAttribute(this.parentNode, 'anonid', 'dropmarker'))"
onpopuphidden="runTest('tb2')">
<menuitem label="Item"/>
</menupopup>
</toolbarbutton>
<toolbarbutton id="tb2" type="menu" label="Open" anchor="someanchor">
<menupopup id="popup2" onpopupshown="checkPopup(this, $('someanchor'))" onpopuphidden="runTest('tb3')">
<menuitem label="Item"/>
</menupopup>
</toolbarbutton>
<toolbarbutton id="tb3" type="menu" label="Open" anchor="noexist">
<menupopup id="popup3" onpopupshown="checkPopup(this, this.parentNode)" onpopuphidden="SimpleTest.finish()">
<menuitem label="Item"/>
</menupopup>
</toolbarbutton>
</hbox>
<hbox pack="end" width="180">
<button id="someanchor" label="Anchor"/>
</hbox>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
<script type="application/javascript"><![CDATA[
function runTest(menuid)
{
let menu = $(menuid);
let dropmarker = document.getAnonymousElementByAttribute(menu, "anonid", "dropmarker");
synthesizeMouseAtCenter(dropmarker, { });
}
function isWithinHalfPixel(a, b)
{
return Math.abs(a - b) <= 0.5;
}
function checkPopup(popup, anchor)
{
let popupRect = popup.getBoundingClientRect();
let anchorRect = anchor.getBoundingClientRect();
ok(isWithinHalfPixel(popupRect.left, anchorRect.left), popup.id + " left");
ok(isWithinHalfPixel(popupRect.top, anchorRect.bottom), popup.id + " top");
popup.hidePopup();
}
SimpleTest.waitForExplicitFinish();
]]>
</script>
</window>

View File

@ -214,8 +214,6 @@
MozXULElement.implementCustomInterface(MozButtonBase, [Ci.nsIDOMXULButtonElement]);
MozElements.ButtonBase = MozButtonBase;
class MozButton extends MozButtonBase {
static get inheritedAttributes() {
return {

View File

@ -0,0 +1,192 @@
<?xml version="1.0"?>
<!-- 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/. -->
<bindings id="buttonBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="button-base" extends="chrome://global/content/bindings/general.xml#basetext">
<implementation implements="nsIDOMXULButtonElement">
<property name="type"
onget="return this.getAttribute('type');"
onset="this.setAttribute('type', val); return val;"/>
<property name="dlgType"
onget="return this.getAttribute('dlgtype');"
onset="this.setAttribute('dlgtype', val); return val;"/>
<property name="group"
onget="return this.getAttribute('group');"
onset="this.setAttribute('group', val); return val;"/>
<property name="open" onget="return this.hasAttribute('open');">
<setter><![CDATA[
if (this.hasMenu()) {
this.openMenu(val);
} else if (val) {
// Fall back to just setting the attribute
this.setAttribute("open", "true");
} else {
this.removeAttribute("open");
}
return val;
]]></setter>
</property>
<property name="checked" onget="return this.hasAttribute('checked');">
<setter><![CDATA[
if (this.type == "radio" && val) {
var sibs = this.parentNode.getElementsByAttribute("group", this.group);
for (var i = 0; i < sibs.length; ++i)
sibs[i].removeAttribute("checked");
}
if (val)
this.setAttribute("checked", "true");
else
this.removeAttribute("checked");
return val;
]]></setter>
</property>
<method name ="filterButtons">
<parameter name="node"/>
<body>
<![CDATA[
// if the node isn't visible, don't descend into it.
var cs = node.ownerGlobal.getComputedStyle(node);
if (cs.visibility != "visible" || cs.display == "none") {
return NodeFilter.FILTER_REJECT;
}
// but it may be a popup element, in which case we look at "state"...
if (cs.display == "-moz-popup" && node.state != "open") {
return NodeFilter.FILTER_REJECT;
}
// OK - the node seems visible, so it is a candidate.
if (node.localName == "button" && node.accessKey && !node.disabled)
return NodeFilter.FILTER_ACCEPT;
return NodeFilter.FILTER_SKIP;
]]>
</body>
</method>
<method name="fireAccessKeyButton">
<parameter name="aSubtree"/>
<parameter name="aAccessKeyLower"/>
<body>
<![CDATA[
var iterator = aSubtree.ownerDocument.createTreeWalker(aSubtree,
NodeFilter.SHOW_ELEMENT,
this.filterButtons);
while (iterator.nextNode()) {
var test = iterator.currentNode;
if (test.accessKey.toLowerCase() == aAccessKeyLower &&
!test.disabled && !test.collapsed && !test.hidden) {
test.focus();
test.click();
return true;
}
}
return false;
]]>
</body>
</method>
<method name="_handleClick">
<body>
<![CDATA[
if (!this.disabled) {
if (this.type == "checkbox") {
this.checked = !this.checked;
} else if (this.type == "radio") {
this.checked = true;
}
}
]]>
</body>
</method>
</implementation>
<handlers>
<!-- While it would seem we could do this by handling oncommand, we can't
because any external oncommand handlers might get called before ours,
and then they would see the incorrect value of checked. Additionally
a command attribute would redirect the command events anyway.-->
<handler event="click" button="0" action="this._handleClick();"/>
<handler event="keypress" key=" ">
<![CDATA[
this._handleClick();
// Prevent page from scrolling on the space key.
event.preventDefault();
]]>
</handler>
<handler event="keypress">
<![CDATA[
if (this.hasMenu()) {
if (this.open)
return;
} else {
if (event.keyCode == KeyEvent.DOM_VK_UP ||
(event.keyCode == KeyEvent.DOM_VK_LEFT &&
document.defaultView.getComputedStyle(this.parentNode)
.direction == "ltr") ||
(event.keyCode == KeyEvent.DOM_VK_RIGHT &&
document.defaultView.getComputedStyle(this.parentNode)
.direction == "rtl")) {
event.preventDefault();
window.document.commandDispatcher.rewindFocus();
return;
}
if (event.keyCode == KeyEvent.DOM_VK_DOWN ||
(event.keyCode == KeyEvent.DOM_VK_RIGHT &&
document.defaultView.getComputedStyle(this.parentNode)
.direction == "ltr") ||
(event.keyCode == KeyEvent.DOM_VK_LEFT &&
document.defaultView.getComputedStyle(this.parentNode)
.direction == "rtl")) {
event.preventDefault();
window.document.commandDispatcher.advanceFocus();
return;
}
}
if (event.keyCode || event.charCode <= 32 || event.altKey ||
event.ctrlKey || event.metaKey)
return; // No printable char pressed, not a potential accesskey
// Possible accesskey pressed
var charPressedLower = String.fromCharCode(event.charCode).toLowerCase();
// If the accesskey of the current button is pressed, just activate it
if (this.accessKey.toLowerCase() == charPressedLower) {
this.click();
return;
}
// Search for accesskey in the list of buttons for this doc and each subdoc
// Get the buttons for the main document and all sub-frames
for (var frameCount = -1; frameCount < window.top.frames.length; frameCount++) {
var doc = (frameCount == -1) ? window.top.document :
window.top.frames[frameCount].document;
if (this.fireAccessKeyButton(doc.documentElement, charPressedLower))
return;
}
// Test anonymous buttons
var dlg = window.top.document;
var buttonBox = dlg.getAnonymousElementByAttribute(dlg.documentElement,
"anonid", "buttons");
if (buttonBox)
this.fireAccessKeyButton(buttonBox, charPressedLower);
]]>
</handler>
</handlers>
</binding>
</bindings>

View File

@ -1,153 +0,0 @@
/* 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";
// This is loaded into all XUL windows. Wrap in a block to prevent
// leaking to window scope.
{
const KEEP_CHILDREN = new Set(["observes", "template", "menupopup", "panel", "tooltip"]);
window.addEventListener("popupshowing", (e) => {
if (e.originalTarget.ownerDocument != document) {
return;
}
e.originalTarget.setAttribute("hasbeenopened", "true");
for (let el of e.originalTarget.querySelectorAll("toolbarbutton")) {
el.render();
}
}, {capture: true});
class MozToolbarbutton extends MozElements.ButtonBase {
static get inheritedAttributes() {
return {
".toolbarbutton-icon": "validate,src=image,label,type,consumeanchor,triggeringprincipal=iconloadingprincipal",
".toolbarbutton-text": "value=label,accesskey,crop,dragover-top,wrap",
".toolbarbutton-multiline-text": "text=label,accesskey,wrap",
".toolbarbutton-menu-dropmarker": "disabled,label",
".toolbarbutton-badge": "value=badge,style=badgeStyle",
};
}
static get fragment() {
let frag = document.importNode(MozXULElement.parseXULToFragment(`
<image class="toolbarbutton-icon"></image>
<label class="toolbarbutton-text" crop="right" flex="1"></label>
<label class="toolbarbutton-multiline-text" flex="1"></label>
<dropmarker type="menu" class="toolbarbutton-menu-dropmarker"></dropmarker>`), true);
Object.defineProperty(this, "fragment", {value: frag});
return frag;
}
static get badgedFragment() {
let frag = document.importNode(MozXULElement.parseXULToFragment(`
<stack class="toolbarbutton-badge-stack">
<image class="toolbarbutton-icon"/>
<label class="toolbarbutton-badge" top="0" end="0" crop="none"/>
</stack>
<label class="toolbarbutton-text" crop="right" flex="1"/>
<label class="toolbarbutton-multiline-text" flex="1"/>
<dropmarker anonid="dropmarker" type="menu"
class="toolbarbutton-menu-dropmarker"/>`), true);
Object.defineProperty(this, "badgedFragment", {value: frag});
return frag;
}
get _hasRendered() {
return (this.querySelector(":scope > .toolbarbutton-text") != null);
}
connectedCallback() {
if (this.delayConnectedCallback()) {
return;
}
// Defer creating DOM elements for content inside popups.
// These will be added in the popupshown handler above.
let panel = this.closest("panel");
if (panel && !panel.hasAttribute("hasbeenopened")) {
return;
}
this.render();
}
render() {
if (this._hasRendered) {
return;
}
let badged = (this.getAttribute("badged") == "true");
if (badged) {
let moveChildren = [];
for (let child of this.children) {
if (!KEEP_CHILDREN.has(child.tagName)) {
moveChildren.push(child);
}
}
this.appendChild(this.constructor.badgedFragment.cloneNode(true));
if (moveChildren.length > 0) {
let {badgeStack, icon} = this;
for (let child of moveChildren) {
badgeStack.insertBefore(child, icon);
}
}
} else {
let moveChildren = [];
for (let child of this.children) {
if (!KEEP_CHILDREN.has(child.tagName) && child.tagName != "box") {
// XBL toolbarbutton doesn't insert any anonymous content
// if it has a child of any other type
return;
}
if (child.tagName == "box") {
moveChildren.push(child);
}
}
this.appendChild(this.constructor.fragment.cloneNode(true));
// XBL toolbarbutton explicitly places any <box> children
// right before the menu marker.
for (let child of moveChildren) {
this.insertBefore(child, this.lastChild);
}
}
this.initializeAttributeInheritance();
}
get icon() {
return this.querySelector(".toolbarbutton-icon");
}
get badgeLabel() {
return this.querySelector(".toolbarbutton-badge");
}
get badgeStack() {
return this.querySelector(".toolbarbutton-badge-stack");
}
get multilineLabel() {
return this.querySelector(".toolbarbutton-multiline-text");
}
get dropmarker() {
return this.querySelector(".toolbarbutton-menu-dropmarker");
}
get menupopup() {
return this.querySelector("menupopup");
}
}
customElements.define("toolbarbutton", MozToolbarbutton);
}

View File

@ -0,0 +1,48 @@
<?xml version="1.0"?>
<!-- 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/. -->
<bindings id="toolbarbuttonBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="toolbarbutton"
extends="chrome://global/content/bindings/button.xml#button-base">
<implementation>
<property name="multilineLabel"
onget="return document.getAnonymousElementByAttribute(this, 'class', 'toolbarbutton-multiline-text');" />
</implementation>
<content>
<children includes="observes|template|menupopup|panel|tooltip"/>
<xul:image class="toolbarbutton-icon" xbl:inherits="validate,src=image,label,type,consumeanchor,triggeringprincipal=iconloadingprincipal"/>
<xul:label class="toolbarbutton-text" crop="right" flex="1"
xbl:inherits="value=label,accesskey,crop,dragover-top,wrap"/>
<xul:label class="toolbarbutton-multiline-text" flex="1"
xbl:inherits="xbl:text=label,accesskey,wrap"/>
<children includes="box"/>
<xul:dropmarker anonid="dropmarker" type="menu"
class="toolbarbutton-menu-dropmarker" xbl:inherits="disabled,label"/>
</content>
</binding>
<binding id="toolbarbutton-badged"
extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton">
<content>
<children includes="observes|template|menupopup|panel|tooltip"/>
<xul:stack class="toolbarbutton-badge-stack">
<children/>
<xul:image class="toolbarbutton-icon" xbl:inherits="validate,src=image,label,consumeanchor"/>
<xul:label class="toolbarbutton-badge" xbl:inherits="value=badge,style=badgeStyle" top="0" end="0" crop="none"/>
</xul:stack>
<xul:label class="toolbarbutton-text" crop="right" flex="1"
xbl:inherits="value=label,accesskey,crop,wrap"/>
<xul:label class="toolbarbutton-multiline-text" flex="1"
xbl:inherits="xbl:text=label,accesskey,wrap"/>
<xul:dropmarker anonid="dropmarker" type="menu"
class="toolbarbutton-menu-dropmarker" xbl:inherits="disabled,label"/>
</content>
</binding>
</bindings>

View File

@ -107,6 +107,15 @@ label html|span.accesskey {
/********** toolbarbutton **********/
toolbarbutton {
-moz-binding: url("chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton");
}
toolbarbutton.badged-button > toolbarbutton,
toolbarbutton.badged-button {
-moz-binding: url("chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-badged");
}
.toolbarbutton-badge:not([value]),
.toolbarbutton-badge[value=""] {
display: none;