diff --git a/browser/base/content/test/performance/browser_appmenu.js b/browser/base/content/test/performance/browser_appmenu.js index 236144e80bf5..52d4657801d9 100644 --- a/browser/base/content/test/performance/browser_appmenu.js +++ b/browser/base/content/test/performance/browser_appmenu.js @@ -16,14 +16,12 @@ let gCUITestUtils = new CustomizableUITestUtils(window); const EXPECTED_APPMENU_OPEN_REFLOWS = [ { stack: [ - "openPopup@chrome://global/content/bindings/popup.xml", "openPopup/this._openPopupPromise<@resource:///modules/PanelMultiView.jsm", ], }, { stack: [ - "get_alignmentPosition@chrome://global/content/bindings/popup.xml", "adjustArrowPosition@chrome://global/content/bindings/popup.xml", "onxblpopuppositioned@chrome://global/content/bindings/popup.xml", ], @@ -31,21 +29,13 @@ const EXPECTED_APPMENU_OPEN_REFLOWS = [ maxCount: 3, // This number should only ever go down - never up. }, - { - stack: [ - "get_alignmentPosition@chrome://global/content/bindings/popup.xml", - "_calculateMaxHeight@resource:///modules/PanelMultiView.jsm", - "handleEvent@resource:///modules/PanelMultiView.jsm", - ], - }, - { stack: [ "_calculateMaxHeight@resource:///modules/PanelMultiView.jsm", "handleEvent@resource:///modules/PanelMultiView.jsm", ], - maxCount: 6, // This number should only ever go down - never up. + maxCount: 7, // This number should only ever go down - never up. }, ]; diff --git a/browser/base/content/test/performance/browser_urlbar_keyed_search.js b/browser/base/content/test/performance/browser_urlbar_keyed_search.js index 7b4ff80ce763..6c9c91d5e3e8 100644 --- a/browser/base/content/test/performance/browser_urlbar_keyed_search.js +++ b/browser/base/content/test/performance/browser_urlbar_keyed_search.js @@ -23,7 +23,6 @@ const EXPECTED_REFLOWS_FIRST_OPEN = [ "enableOneOffSearches@chrome://browser/content/urlbarBindings.xml", "_enableOrDisableOneOffSearches@chrome://browser/content/urlbarBindings.xml", "urlbar_XBL_Constructor/<@chrome://browser/content/urlbarBindings.xml", - "openPopup@chrome://global/content/bindings/popup.xml", "_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml", "openAutocompletePopup@chrome://browser/content/urlbarBindings.xml", "openPopup@chrome://global/content/bindings/autocomplete.xml", @@ -74,7 +73,6 @@ const EXPECTED_REFLOWS_FIRST_OPEN = [ // Bug 1359989 { stack: [ - "openPopup@chrome://global/content/bindings/popup.xml", "_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml", "openAutocompletePopup@chrome://browser/content/urlbarBindings.xml", "openPopup@chrome://global/content/bindings/autocomplete.xml", diff --git a/browser/base/content/test/performance/browser_urlbar_search.js b/browser/base/content/test/performance/browser_urlbar_search.js index 405700d39cb2..bb38bcf93d79 100644 --- a/browser/base/content/test/performance/browser_urlbar_search.js +++ b/browser/base/content/test/performance/browser_urlbar_search.js @@ -23,7 +23,6 @@ const EXPECTED_REFLOWS_FIRST_OPEN = [ "enableOneOffSearches@chrome://browser/content/urlbarBindings.xml", "_enableOrDisableOneOffSearches@chrome://browser/content/urlbarBindings.xml", "urlbar_XBL_Constructor/<@chrome://browser/content/urlbarBindings.xml", - "openPopup@chrome://global/content/bindings/popup.xml", "_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml", "openAutocompletePopup@chrome://browser/content/urlbarBindings.xml", "openPopup@chrome://global/content/bindings/autocomplete.xml", @@ -74,7 +73,6 @@ const EXPECTED_REFLOWS_FIRST_OPEN = [ // Bug 1359989 { stack: [ - "openPopup@chrome://global/content/bindings/popup.xml", "_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml", "openAutocompletePopup@chrome://browser/content/urlbarBindings.xml", "openPopup@chrome://global/content/bindings/autocomplete.xml", @@ -116,7 +114,6 @@ const EXPECTED_REFLOWS_SECOND_OPEN = [ // Bug 1359989 { stack: [ - "openPopup@chrome://global/content/bindings/popup.xml", "_openAutocompletePopup@chrome://browser/content/urlbarBindings.xml", "openAutocompletePopup@chrome://browser/content/urlbarBindings.xml", "openPopup@chrome://global/content/bindings/autocomplete.xml", diff --git a/devtools/server/actors/inspector/node.js b/devtools/server/actors/inspector/node.js index 10edb20f319d..8aba9923a11a 100644 --- a/devtools/server/actors/inspector/node.js +++ b/devtools/server/actors/inspector/node.js @@ -408,7 +408,7 @@ const NodeActor = protocol.ActorClassWithSpec(nodeSpec, { let url = ""; // If the listener is an object with a 'handleEvent' method, use that. - if (listenerDO.class === "Object" || listenerDO.class === "XULElement") { + if (listenerDO.class === "Object" || /^XUL\w*Element$/.test(listenerDO.class)) { let desc; while (!desc && listenerDO) { diff --git a/devtools/server/actors/thread.js b/devtools/server/actors/thread.js index 2abb6f19fdb3..3ab7c4c4b49f 100644 --- a/devtools/server/actors/thread.js +++ b/devtools/server/actors/thread.js @@ -1146,7 +1146,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, { // Get the Debugger.Object for the listener object. let listenerDO = this.globalDebugObject.makeDebuggeeValue(listener); // If the listener is an object with a 'handleEvent' method, use that. - if (listenerDO.class == "Object" || listenerDO.class == "XULElement") { + if (listenerDO.class === "Object" || /^XUL\w*Element$/.test(listenerDO.class)) { // For some events we don't have permission to access the // 'handleEvent' property when running in content scope. if (!listenerDO.unwrap()) { diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 5f7f77ff2cfa..b3648acd749b 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -256,7 +256,6 @@ #ifdef MOZ_XUL #include "mozilla/dom/ListBoxObject.h" #include "mozilla/dom/MenuBoxObject.h" -#include "mozilla/dom/PopupBoxObject.h" #include "mozilla/dom/ScrollBoxObject.h" #include "mozilla/dom/TreeBoxObject.h" #endif @@ -6576,11 +6575,6 @@ nsIDocument::GetBoxObjectFor(Element* aElement, ErrorResult& aRv) if (namespaceID == kNameSpaceID_XUL) { if (tag == nsGkAtoms::menu) { boxObject = new MenuBoxObject(); - } else if (tag == nsGkAtoms::popup || - tag == nsGkAtoms::menupopup || - tag == nsGkAtoms::panel || - tag == nsGkAtoms::tooltip) { - boxObject = new PopupBoxObject(); } else if (tag == nsGkAtoms::tree) { boxObject = new TreeBoxObject(); } else if (tag == nsGkAtoms::listbox) { diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index eccec05356df..242c2d5ce0c7 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -107,10 +107,6 @@ DOMInterfaces = { 'headerFile': 'BatteryManager.h' }, -'BoxObject': { - 'resultNotAddRefed': ['element'], -}, - 'Cache': { 'implicitJSContext': [ 'add', 'addAll', 'match', 'matchAll', 'put', 'delete', 'keys' ], @@ -691,10 +687,6 @@ DOMInterfaces = { 'nativeType': 'nsIPluginTag', }, -'PopupBoxObject': { - 'resultNotAddRefed': ['triggerNode', 'anchorNode'], -}, - 'Position': { 'headerFile': 'nsGeoPosition.h' }, diff --git a/dom/tests/mochitest/general/test_interfaces.js b/dom/tests/mochitest/general/test_interfaces.js index d132195ef497..cec0478ee1ef 100644 --- a/dom/tests/mochitest/general/test_interfaces.js +++ b/dom/tests/mochitest/general/test_interfaces.js @@ -788,8 +788,6 @@ var interfaceNamesInGlobalScope = {name: "PopStateEvent", insecureContext: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "PopupBlockedEvent", insecureContext: true}, -// IMPORTANT: Do not change this list without review from a DOM peer! - {name: "PopupBoxObject", insecureContext: true, xbl: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "Presentation", insecureContext: true, desktop: false, release: false }, // IMPORTANT: Do not change this list without review from a DOM peer! @@ -1268,6 +1266,8 @@ var interfaceNamesInGlobalScope = {name: "XULDocument", insecureContext: true, xbl: true}, // IMPORTANT: Do not change this list without review from a DOM peer! {name: "XULElement", insecureContext: true, xbl: true}, +// IMPORTANT: Do not change this list without review from a DOM peer! + {name: "XULPopupElement", insecureContext: true, xbl: true}, // IMPORTANT: Do not change this list without review from a DOM peer! ]; // IMPORTANT: Do not change the list above without review from a DOM peer! diff --git a/dom/webidl/PopupBoxObject.webidl b/dom/webidl/XULPopupElement.webidl similarity index 83% rename from dom/webidl/PopupBoxObject.webidl rename to dom/webidl/XULPopupElement.webidl index 2e2fec55cc0b..a6e5b7b2dcff 100644 --- a/dom/webidl/PopupBoxObject.webidl +++ b/dom/webidl/XULPopupElement.webidl @@ -20,8 +20,8 @@ dictionary OpenPopupOptions { typedef (DOMString or OpenPopupOptions) StringOrOpenPopupOptions; -[Func="IsChromeOrXBL"] -interface PopupBoxObject : BoxObject +[HTMLConstructor, Func="IsChromeOrXBL"] +interface XULPopupElement : XULElement { /** * Allow the popup to automatically position itself. @@ -84,9 +84,9 @@ interface PopupBoxObject : BoxObject * @param y vertical screen position * @param triggerEvent the event that triggered this popup (mouse click for example) */ - void openPopupAtScreen(long x, long y, - boolean isContextMenu, - Event? triggerEvent); + void openPopupAtScreen(optional long x = 0, optional long y = 0, + optional boolean isContextMenu = false, + optional Event? triggerEvent = null); /** * Open the popup anchored at a specific screen rectangle. This function is @@ -95,13 +95,13 @@ interface PopupBoxObject : BoxObject * coordinates. */ void openPopupAtScreenRect(optional DOMString position = "", - long x, - long y, - long width, - long height, - boolean isContextMenu, - boolean attributesOverride, - Event? triggerEvent); + optional long x = 0, + optional long y = 0, + optional long width = 0, + optional long height = 0, + optional boolean isContextMenu = false, + optional boolean attributesOverride = false, + optional Event? triggerEvent = null); /** * Hide the popup if it is open. The cancel argument is used as a hint that @@ -112,6 +112,18 @@ interface PopupBoxObject : BoxObject */ void hidePopup(optional boolean cancel = false); + /** + * Attribute getter and setter for label. + */ + [SetterThrows] + attribute DOMString label; + + /** + * Attribute getter and setter for position. + */ + [SetterThrows] + attribute DOMString position; + /** * Returns the state of the popup: * closed - the popup is closed @@ -119,7 +131,7 @@ interface PopupBoxObject : BoxObject * showing - the popup is in the process of being shown * hiding - the popup is in the process of being hidden */ - readonly attribute DOMString popupState; + readonly attribute DOMString state; /** * The node that triggered the popup. If the popup is not open, will return @@ -149,10 +161,10 @@ interface PopupBoxObject : BoxObject * meaning as the corresponding argument to openPopup. This method has no effect * on popups that are not open. */ - void moveToAnchor(Element? anchorElement, + void moveToAnchor(optional Element? anchorElement = null, optional DOMString position = "", - long x, long y, - boolean attributesOverride); + optional long x = 0, optional long y = 0, + optional boolean attributesOverride = false); /** * Size the popup to the given dimensions diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index bfa40c90f954..decc095012ee 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -721,7 +721,6 @@ WEBIDL_FILES = [ 'Plugin.webidl', 'PluginArray.webidl', 'PointerEvent.webidl', - 'PopupBoxObject.webidl', 'Position.webidl', 'PositionError.webidl', 'Presentation.webidl', @@ -953,6 +952,7 @@ WEBIDL_FILES = [ 'XULCommandEvent.webidl', 'XULDocument.webidl', 'XULElement.webidl', + 'XULPopupElement.webidl', ] if CONFIG['MOZ_WEBRTC']: diff --git a/layout/xul/PopupBoxObject.cpp b/dom/xul/XULPopupElement.cpp similarity index 60% rename from layout/xul/PopupBoxObject.cpp rename to dom/xul/XULPopupElement.cpp index 3ce61154927e..c4c1245c0693 100644 --- a/layout/xul/PopupBoxObject.cpp +++ b/dom/xul/XULPopupElement.cpp @@ -14,48 +14,46 @@ #include "nsView.h" #include "mozilla/AppUnits.h" #include "mozilla/dom/DOMRect.h" -#include "mozilla/dom/PopupBoxObject.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/Event.h" -#include "mozilla/dom/PopupBoxObjectBinding.h" +#include "mozilla/dom/XULPopupElement.h" +#include "mozilla/dom/XULPopupElementBinding.h" namespace mozilla { namespace dom { -PopupBoxObject::PopupBoxObject() +nsXULElement* +NS_NewXULPopupElement(already_AddRefed&& aNodeInfo) { + return new XULPopupElement(aNodeInfo); } -PopupBoxObject::~PopupBoxObject() +JSObject* +XULPopupElement::WrapNode(JSContext *aCx, JS::Handle aGivenProto) { + return XULPopupElementBinding::Wrap(aCx, this, aGivenProto); } -nsIContent* PopupBoxObject::GetParentObject() const +nsIFrame* +XULPopupElement::GetFrame(bool aFlushLayout) { - return BoxObject::GetParentObject(); -} + nsCOMPtr kungFuDeathGrip = this; // keep a reference -JSObject* PopupBoxObject::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return PopupBoxObjectBinding::Wrap(aCx, this, aGivenProto); -} - -void -PopupBoxObject::HidePopup(bool aCancel) -{ - nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); - if (pm && mContent) { - pm->HidePopup(mContent, false, true, false, aCancel); + nsCOMPtr doc = GetUncomposedDoc(); + if (doc) { + doc->FlushPendingNotifications(aFlushLayout ? FlushType::Layout : FlushType::Frames); } + + return GetPrimaryFrame(); } void -PopupBoxObject::OpenPopup(Element* aAnchorElement, - const StringOrOpenPopupOptions& aOptions, - int32_t aXPos, int32_t aYPos, - bool aIsContextMenu, - bool aAttributesOverride, - Event* aTriggerEvent) +XULPopupElement::OpenPopup(Element* aAnchorElement, + const StringOrOpenPopupOptions& aOptions, + int32_t aXPos, int32_t aYPos, + bool aIsContextMenu, + bool aAttributesOverride, + Event* aTriggerEvent) { nsAutoString position; if (aOptions.IsOpenPopupOptions()) { @@ -72,107 +70,109 @@ PopupBoxObject::OpenPopup(Element* aAnchorElement, } nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); - if (pm && mContent) { + if (pm) { // As a special case for popups that are menus when no anchor or position are // specified, open the popup with ShowMenu instead of ShowPopup so that the // popup is aligned with the menu. - if (!aAnchorElement && position.IsEmpty() && mContent->GetPrimaryFrame()) { - nsMenuFrame* menu = do_QueryFrame(mContent->GetPrimaryFrame()->GetParent()); + if (!aAnchorElement && position.IsEmpty() && GetPrimaryFrame()) { + nsMenuFrame* menu = do_QueryFrame(GetPrimaryFrame()->GetParent()); if (menu) { pm->ShowMenu(menu->GetContent(), false, false); return; } } - nsCOMPtr anchorContent(do_QueryInterface(aAnchorElement)); - pm->ShowPopup(mContent, anchorContent, position, aXPos, aYPos, + pm->ShowPopup(this, aAnchorElement, position, aXPos, aYPos, aIsContextMenu, aAttributesOverride, false, aTriggerEvent); } } void -PopupBoxObject::OpenPopupAtScreen(int32_t aXPos, int32_t aYPos, - bool aIsContextMenu, - Event* aTriggerEvent) +XULPopupElement::OpenPopupAtScreen(int32_t aXPos, int32_t aYPos, + bool aIsContextMenu, + Event* aTriggerEvent) { nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); - if (pm && mContent) - pm->ShowPopupAtScreen(mContent, aXPos, aYPos, aIsContextMenu, aTriggerEvent); + if (pm) { + pm->ShowPopupAtScreen(this, aXPos, aYPos, aIsContextMenu, aTriggerEvent); + } } void -PopupBoxObject::OpenPopupAtScreenRect(const nsAString& aPosition, - int32_t aXPos, int32_t aYPos, - int32_t aWidth, int32_t aHeight, - bool aIsContextMenu, - bool aAttributesOverride, - Event* aTriggerEvent) +XULPopupElement::OpenPopupAtScreenRect(const nsAString& aPosition, + int32_t aXPos, int32_t aYPos, + int32_t aWidth, int32_t aHeight, + bool aIsContextMenu, + bool aAttributesOverride, + Event* aTriggerEvent) { nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); - if (pm && mContent) { - pm->ShowPopupAtScreenRect(mContent, aPosition, + if (pm) { + pm->ShowPopupAtScreenRect(this, aPosition, nsIntRect(aXPos, aYPos, aWidth, aHeight), aIsContextMenu, aAttributesOverride, aTriggerEvent); } } void -PopupBoxObject::MoveTo(int32_t aLeft, int32_t aTop) +XULPopupElement::HidePopup(bool aCancel) { - nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr; + nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); + if (pm) { + pm->HidePopup(this, false, true, false, aCancel); + } +} + +void +XULPopupElement::MoveTo(int32_t aLeft, int32_t aTop) +{ + nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame()); if (menuPopupFrame) { menuPopupFrame->MoveTo(CSSIntPoint(aLeft, aTop), true); } } void -PopupBoxObject::MoveToAnchor(Element* aAnchorElement, - const nsAString& aPosition, - int32_t aXPos, int32_t aYPos, - bool aAttributesOverride) +XULPopupElement::MoveToAnchor(Element* aAnchorElement, + const nsAString& aPosition, + int32_t aXPos, int32_t aYPos, + bool aAttributesOverride) { - if (mContent) { - nsCOMPtr anchorContent(do_QueryInterface(aAnchorElement)); - - nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(mContent->GetPrimaryFrame()); - if (menuPopupFrame && menuPopupFrame->IsVisible()) { - menuPopupFrame->MoveToAnchor(anchorContent, aPosition, aXPos, aYPos, aAttributesOverride); - } + nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame()); + if (menuPopupFrame && menuPopupFrame->IsVisible()) { + menuPopupFrame->MoveToAnchor(aAnchorElement, aPosition, aXPos, aYPos, aAttributesOverride); } } void -PopupBoxObject::SizeTo(int32_t aWidth, int32_t aHeight) +XULPopupElement::SizeTo(int32_t aWidth, int32_t aHeight) { - if (!mContent) - return; - nsAutoString width, height; width.AppendInt(aWidth); height.AppendInt(aHeight); - RefPtr element = mContent->AsElement(); + nsCOMPtr kungFuDeathGrip = this; // keep a reference // We only want to pass aNotify=true to SetAttr once, but must make sure // we pass it when a value is being changed. Thus, we check if the height // is the same and if so, pass true when setting the width. - bool heightSame = element->AttrValueIs(kNameSpaceID_None, nsGkAtoms::height, height, eCaseMatters); + bool heightSame = AttrValueIs(kNameSpaceID_None, nsGkAtoms::height, height, eCaseMatters); - element->SetAttr(kNameSpaceID_None, nsGkAtoms::width, width, heightSame); - element->SetAttr(kNameSpaceID_None, nsGkAtoms::height, height, true); + SetAttr(kNameSpaceID_None, nsGkAtoms::width, width, heightSame); + SetAttr(kNameSpaceID_None, nsGkAtoms::height, height, true); // If the popup is open, force a reposition of the popup after resizing it // with notifications set to true so that the popuppositioned event is fired. - nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(mContent->GetPrimaryFrame()); + nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame()); if (menuPopupFrame && menuPopupFrame->PopupState() == ePopupShown) { menuPopupFrame->SetPopupPosition(nullptr, false, false, true); } } bool -PopupBoxObject::AutoPosition() +XULPopupElement::AutoPosition() { - nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr; + nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame()); if (menuPopupFrame) { return menuPopupFrame->GetAutoPosition(); } @@ -180,21 +180,21 @@ PopupBoxObject::AutoPosition() } void -PopupBoxObject::SetAutoPosition(bool aShouldAutoPosition) +XULPopupElement::SetAutoPosition(bool aShouldAutoPosition) { - nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr; + nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame()); if (menuPopupFrame) { menuPopupFrame->SetAutoPosition(aShouldAutoPosition); } } void -PopupBoxObject::GetPopupState(nsString& aState) +XULPopupElement::GetState(nsString& aState) { // set this here in case there's no frame for the popup aState.AssignLiteral("closed"); - nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr; + nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame()); if (menuPopupFrame) { switch (menuPopupFrame->PopupState()) { case ePopupShown: @@ -220,16 +220,16 @@ PopupBoxObject::GetPopupState(nsString& aState) } nsINode* -PopupBoxObject::GetTriggerNode() const +XULPopupElement::GetTriggerNode() const { - nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr; + nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame()); return nsMenuPopupFrame::GetTriggerContent(menuPopupFrame); } Element* -PopupBoxObject::GetAnchorNode() const +XULPopupElement::GetAnchorNode() const { - nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr; + nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetPrimaryFrame()); if (!menuPopupFrame) { return nullptr; } @@ -239,9 +239,9 @@ PopupBoxObject::GetAnchorNode() const } already_AddRefed -PopupBoxObject::GetOuterScreenRect() +XULPopupElement::GetOuterScreenRect() { - RefPtr rect = new DOMRect(mContent); + RefPtr rect = new DOMRect(ToSupports(this)); // Return an empty rectangle if the popup is not open. nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false)); @@ -263,7 +263,7 @@ PopupBoxObject::GetOuterScreenRect() } void -PopupBoxObject::GetAlignmentPosition(nsString& positionStr) +XULPopupElement::GetAlignmentPosition(nsString& positionStr) { positionStr.Truncate(); @@ -314,7 +314,7 @@ PopupBoxObject::GetAlignmentPosition(nsString& positionStr) } int32_t -PopupBoxObject::AlignmentOffset() +XULPopupElement::AlignmentOffset() { nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false)); if (!menuPopupFrame) @@ -330,7 +330,7 @@ PopupBoxObject::AlignmentOffset() } void -PopupBoxObject::SetConstraintRect(dom::DOMRectReadOnly& aRect) +XULPopupElement::SetConstraintRect(dom::DOMRectReadOnly& aRect) { nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false)); if (menuPopupFrame) { @@ -341,13 +341,3 @@ PopupBoxObject::SetConstraintRect(dom::DOMRectReadOnly& aRect) } // namespace dom } // namespace mozilla - -// Creation Routine /////////////////////////////////////////////////////////////////////// - -nsresult -NS_NewPopupBoxObject(nsIBoxObject** aResult) -{ - *aResult = new mozilla::dom::PopupBoxObject(); - NS_ADDREF(*aResult); - return NS_OK; -} diff --git a/layout/xul/PopupBoxObject.h b/dom/xul/XULPopupElement.h similarity index 64% rename from layout/xul/PopupBoxObject.h rename to dom/xul/XULPopupElement.h index 36aca723443d..5cc0ca618f54 100644 --- a/layout/xul/PopupBoxObject.h +++ b/dom/xul/XULPopupElement.h @@ -4,15 +4,15 @@ * 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/. */ -#ifndef mozilla_dom_PopupBoxObject_h -#define mozilla_dom_PopupBoxObject_h +#ifndef XULPopupElement_h__ +#define XULPopupElement_h__ #include "mozilla/Attributes.h" #include "mozilla/ErrorResult.h" #include "nsCycleCollectionParticipant.h" #include "nsWrapperCache.h" -#include "mozilla/dom/BoxObject.h" #include "nsString.h" +#include "nsXULElement.h" struct JSContext; @@ -24,22 +24,44 @@ class Element; class Event; class StringOrOpenPopupOptions; -class PopupBoxObject final : public BoxObject +nsXULElement* +NS_NewXULPopupElement(already_AddRefed&& aNodeInfo); + +class XULPopupElement final : public nsXULElement { +private: + nsIFrame* GetFrame(bool aFlushLayout); + public: - NS_INLINE_DECL_REFCOUNTING_INHERITED(PopupBoxObject, BoxObject) + explicit XULPopupElement(already_AddRefed& aNodeInfo) + : nsXULElement(aNodeInfo) + { + } - PopupBoxObject(); + void GetLabel(DOMString& aValue) const + { + GetXULAttr(nsGkAtoms::label, aValue); + } + void SetLabel(const nsAString& aValue, ErrorResult& rv) + { + SetXULAttr(nsGkAtoms::label, aValue, rv); + } - nsIContent* GetParentObject() const; - virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; + void GetPosition(DOMString& aValue) const + { + GetXULAttr(nsGkAtoms::position, aValue); + } + void SetPosition(const nsAString& aValue, ErrorResult& rv) + { + SetXULAttr(nsGkAtoms::position, aValue, rv); + } bool AutoPosition(); void SetAutoPosition(bool aShouldAutoPosition); void OpenPopup(Element* aAnchorElement, - const mozilla::dom::StringOrOpenPopupOptions& aOptions, + const StringOrOpenPopupOptions& aOptions, int32_t aXPos, int32_t aYPos, bool aIsContextMenu, bool aAttributesOverride, @@ -59,7 +81,7 @@ public: void HidePopup(bool aCancel); - void GetPopupState(nsString& aState); + void GetState(nsString& aState); nsINode* GetTriggerNode() const; @@ -81,13 +103,17 @@ public: int32_t AlignmentOffset(); - void SetConstraintRect(dom::DOMRectReadOnly& aRect); + void SetConstraintRect(DOMRectReadOnly& aRect); -private: - ~PopupBoxObject(); +protected: + virtual ~XULPopupElement() + { + } + + JSObject* WrapNode(JSContext *aCx, JS::Handle aGivenProto) override; }; } // namespace dom } // namespace mozilla -#endif // mozilla_dom_PopupBoxObject_h +#endif // XULPopupElement_h diff --git a/dom/xul/moz.build b/dom/xul/moz.build index be2272d02bde..cfa4e18bbfcc 100644 --- a/dom/xul/moz.build +++ b/dom/xul/moz.build @@ -23,6 +23,10 @@ if CONFIG['MOZ_XUL']: 'nsXULElement.h', ] + EXPORTS.mozilla.dom += [ + 'XULPopupElement.h', + ] + UNIFIED_SOURCES += [ 'nsXULCommandDispatcher.cpp', 'nsXULContentSink.cpp', @@ -33,6 +37,7 @@ if CONFIG['MOZ_XUL']: 'nsXULPrototypeDocument.cpp', 'nsXULSortService.cpp', 'XULDocument.cpp', + 'XULPopupElement.cpp', ] XPIDL_SOURCES += [ diff --git a/dom/xul/nsXULElement.cpp b/dom/xul/nsXULElement.cpp index cc435d1107c4..57cfbc6ae47d 100644 --- a/dom/xul/nsXULElement.cpp +++ b/dom/xul/nsXULElement.cpp @@ -75,6 +75,7 @@ #include "nsCCUncollectableMarker.h" #include "nsICSSDeclaration.h" #include "nsLayoutUtils.h" +#include "XULPopupElement.h" #include "mozilla/dom/XULElementBinding.h" #include "mozilla/dom/BoxObject.h" @@ -170,9 +171,14 @@ nsXULElement* NS_NewBasicXULElement(already_AddRefed&& a /* static */ nsXULElement* nsXULElement::Construct(already_AddRefed&& aNodeInfo) { - // Check tagname and create other types of elements here - RefPtr nodeInfo = aNodeInfo; + if (nodeInfo->Equals(nsGkAtoms::menupopup) || + nodeInfo->Equals(nsGkAtoms::popup) || + nodeInfo->Equals(nsGkAtoms::panel) || + nodeInfo->Equals(nsGkAtoms::tooltip)) { + return NS_NewXULPopupElement(nodeInfo.forget()); + } + return NS_NewBasicXULElement(nodeInfo.forget()); } diff --git a/dom/xul/nsXULElement.h b/dom/xul/nsXULElement.h index 1ab79d79582a..01d807cf6ed6 100644 --- a/dom/xul/nsXULElement.h +++ b/dom/xul/nsXULElement.h @@ -332,8 +332,8 @@ ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2); #undef XUL_ELEMENT_FLAG_BIT -class nsXULElement final : public nsStyledElement, - public nsIDOMNode +class nsXULElement : public nsStyledElement, + public nsIDOMNode { protected: // Use Construct to construct elements instead of this constructor. diff --git a/layout/build/nsLayoutCID.h b/layout/build/nsLayoutCID.h index 3000c6754485..1972ee015c01 100644 --- a/layout/build/nsLayoutCID.h +++ b/layout/build/nsLayoutCID.h @@ -31,10 +31,6 @@ #define NS_MENUBOXOBJECT_CID \ { 0xaa40253b, 0x4c42, 0x4056, { 0x81, 0x32, 0x37, 0xbc, 0xd0, 0x78, 0x62, 0xfd } } -// {6C392C62-1AB1-4de7-BFC6-ED4F9FC7749A} -#define NS_POPUPBOXOBJECT_CID \ -{ 0x6c392c62, 0x1ab1, 0x4de7, { 0xbf, 0xc6, 0xed, 0x4f, 0x9f, 0xc7, 0x74, 0x9a } } - // {3B581FD4-3497-426c-8F61-3658B971CB80} #define NS_TREEBOXOBJECT_CID \ { 0x3b581fd4, 0x3497, 0x426c, { 0x8f, 0x61, 0x36, 0x58, 0xb9, 0x71, 0xcb, 0x80 } } diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index 75c8bb7dd3f2..76f2e647aa8b 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -304,7 +304,6 @@ nsresult NS_NewBoxObject(nsIBoxObject** aResult); nsresult NS_NewListBoxObject(nsIBoxObject** aResult); nsresult NS_NewScrollBoxObject(nsIBoxObject** aResult); nsresult NS_NewMenuBoxObject(nsIBoxObject** aResult); -nsresult NS_NewPopupBoxObject(nsIBoxObject** aResult); nsresult NS_NewTreeBoxObject(nsIBoxObject** aResult); #endif @@ -366,7 +365,6 @@ MAKE_CTOR(CreateNewBoxObject, nsIBoxObject, NS_NewBoxObject) #ifdef MOZ_XUL MAKE_CTOR(CreateNewListBoxObject, nsIBoxObject, NS_NewListBoxObject) MAKE_CTOR(CreateNewMenuBoxObject, nsIBoxObject, NS_NewMenuBoxObject) -MAKE_CTOR(CreateNewPopupBoxObject, nsIBoxObject, NS_NewPopupBoxObject) MAKE_CTOR(CreateNewScrollBoxObject, nsIBoxObject, NS_NewScrollBoxObject) MAKE_CTOR(CreateNewTreeBoxObject, nsIBoxObject, NS_NewTreeBoxObject) #endif // MOZ_XUL @@ -509,7 +507,6 @@ NS_DEFINE_NAMED_CID(NS_BOXOBJECT_CID); #ifdef MOZ_XUL NS_DEFINE_NAMED_CID(NS_LISTBOXOBJECT_CID); NS_DEFINE_NAMED_CID(NS_MENUBOXOBJECT_CID); -NS_DEFINE_NAMED_CID(NS_POPUPBOXOBJECT_CID); NS_DEFINE_NAMED_CID(NS_SCROLLBOXOBJECT_CID); NS_DEFINE_NAMED_CID(NS_TREEBOXOBJECT_CID); #endif // MOZ_XUL @@ -751,7 +748,6 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = { #ifdef MOZ_XUL { &kNS_LISTBOXOBJECT_CID, false, nullptr, CreateNewListBoxObject }, { &kNS_MENUBOXOBJECT_CID, false, nullptr, CreateNewMenuBoxObject }, - { &kNS_POPUPBOXOBJECT_CID, false, nullptr, CreateNewPopupBoxObject }, { &kNS_SCROLLBOXOBJECT_CID, false, nullptr, CreateNewScrollBoxObject }, { &kNS_TREEBOXOBJECT_CID, false, nullptr, CreateNewTreeBoxObject }, #endif // MOZ_XUL @@ -859,7 +855,6 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = { #ifdef MOZ_XUL { "@mozilla.org/layout/xul-boxobject-listbox;1", &kNS_LISTBOXOBJECT_CID }, { "@mozilla.org/layout/xul-boxobject-menu;1", &kNS_MENUBOXOBJECT_CID }, - { "@mozilla.org/layout/xul-boxobject-popup;1", &kNS_POPUPBOXOBJECT_CID }, { "@mozilla.org/layout/xul-boxobject-scrollbox;1", &kNS_SCROLLBOXOBJECT_CID }, { "@mozilla.org/layout/xul-boxobject-tree;1", &kNS_TREEBOXOBJECT_CID }, #endif // MOZ_XUL diff --git a/layout/xul/moz.build b/layout/xul/moz.build index 31d1f43b3047..86e3b4f72445 100644 --- a/layout/xul/moz.build +++ b/layout/xul/moz.build @@ -35,7 +35,6 @@ EXPORTS.mozilla.dom += [ 'BoxObject.h', 'ListBoxObject.h', 'MenuBoxObject.h', - 'PopupBoxObject.h', 'ScrollBoxObject.h', ] @@ -82,7 +81,6 @@ if CONFIG['MOZ_XUL']: 'nsTitleBarFrame.cpp', 'nsXULLabelFrame.cpp', 'nsXULPopupManager.cpp', - 'PopupBoxObject.cpp', 'ScrollBoxObject.cpp', ] diff --git a/layout/xul/nsMenuPopupFrame.cpp b/layout/xul/nsMenuPopupFrame.cpp index 5797174c7c99..192356b4351c 100644 --- a/layout/xul/nsMenuPopupFrame.cpp +++ b/layout/xul/nsMenuPopupFrame.cpp @@ -2287,7 +2287,7 @@ nsMenuPopupFrame::MoveToAttributePosition() // Move the widget around when the user sets the |left| and |top| attributes. // Note that this is not the best way to move the widget, as it results in lots // of FE notifications and is likely to be slow as molasses. Use |moveTo| on - // PopupBoxObject if possible. + // the element if possible. nsAutoString left, top; mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::left, left); mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::top, top); diff --git a/layout/xul/nsXULPopupManager.h b/layout/xul/nsXULPopupManager.h index 4009843bae43..b5ccc8326efc 100644 --- a/layout/xul/nsXULPopupManager.h +++ b/layout/xul/nsXULPopupManager.h @@ -444,7 +444,7 @@ public: /** * Open a popup, either anchored or unanchored. If aSelectFirstItem is * true, then the first item in the menu is selected. The arguments are - * similar to those for nsIPopupBoxObject::OpenPopup. + * similar to those for XULPopupElement::OpenPopup. * * aTriggerEvent should be the event that triggered the event. This is used * to determine the coordinates and trigger node for the popup. This may be diff --git a/toolkit/content/tests/widgets/test_popupanchor.xul b/toolkit/content/tests/widgets/test_popupanchor.xul index ef8aefa968ff..ae33be538724 100644 --- a/toolkit/content/tests/widgets/test_popupanchor.xul +++ b/toolkit/content/tests/widgets/test_popupanchor.xul @@ -151,22 +151,26 @@ var tests = [ next(); }); }], - ['flippingResizeHorizontal', 'middle', function(next) { openPopup("after_end", function() { isArrowPositionedOn("right"); - panel.sizeTo(anchor.getBoundingClientRect().left + 50, 50); - isArrowPositionedOn("left"); // check it flipped and has zero offset. - next(); + waitForPopupPositioned( + () => { panel.sizeTo(anchor.getBoundingClientRect().left + 50, 50); }, + () => { + isArrowPositionedOn("left"); // check it flipped and has zero offset. + next(); + }); }); }], - ['flippingResizeVertical', 'middle', function(next) { openPopup("start_after", function() { isArrowPositionedOn("bottom"); - panel.sizeTo(50, anchor.getBoundingClientRect().top + 50); - isArrowPositionedOn("top"); // check it flipped and has zero offset. - next(); + waitForPopupPositioned( + () => { panel.sizeTo(50, anchor.getBoundingClientRect().top + 50); }, + () => { + isArrowPositionedOn("top"); // check it flipped and has zero offset. + next(); + }); }); }], @@ -271,13 +275,16 @@ var tests = [ // Now move it such that the arrow can't be at either end of the panel but // instead somewhere in the middle as that is the only way things fit, // meaning the arrow should "slide" down the panel. - panel.sizeTo(window.innerWidth - 10, 60); - is(panel.getBoundingClientRect().width, window.innerWidth - 10, "width is what we requested.") - // the arrow should not have moved. - var curArrowRect = arrow.getBoundingClientRect(); - is_close(curArrowRect.left, origArrowRect.left, "arrow should not have moved"); - is_close(curArrowRect.top, origArrowRect.top, "arrow should not have moved up or down"); - next(); + waitForPopupPositioned( + () => { panel.sizeTo(window.innerWidth - 10, 60); }, + () => { + is(panel.getBoundingClientRect().width, window.innerWidth - 10, "width is what we requested.") + // the arrow should not have moved. + var curArrowRect = arrow.getBoundingClientRect(); + is_close(curArrowRect.left, origArrowRect.left, "arrow should not have moved"); + is_close(curArrowRect.top, origArrowRect.top, "arrow should not have moved up or down"); + next(); + }); }); }], @@ -286,13 +293,16 @@ var tests = [ var origArrowRect = arrow.getBoundingClientRect(); // Now size it such that the arrow can't be at either end of the panel but // instead somewhere in the middle as that is the only way things fit. - panel.sizeTo(window.innerWidth - 10, 60); - is(panel.getBoundingClientRect().width, window.innerWidth - 10, "width is what we requested") - // the arrow should not have moved. - var curArrowRect = arrow.getBoundingClientRect(); - is_close(curArrowRect.left, origArrowRect.left, "arrow should not have moved"); - is_close(curArrowRect.top, origArrowRect.top, "arrow should not have moved up or down"); - next(); + waitForPopupPositioned( + () => { panel.sizeTo(window.innerWidth - 10, 60); }, + () => { + is(panel.getBoundingClientRect().width, window.innerWidth - 10, "width is what we requested") + // the arrow should not have moved. + var curArrowRect = arrow.getBoundingClientRect(); + is_close(curArrowRect.left, origArrowRect.left, "arrow should not have moved"); + is_close(curArrowRect.top, origArrowRect.top, "arrow should not have moved up or down"); + next(); + }); }); }], @@ -302,13 +312,16 @@ var tests = [ // Now move it such that the arrow can't be at either end of the panel but // instead somewhere in the middle as that is the only way things fit, // meaning the arrow should "slide" down the panel. - panel.sizeTo(100, window.innerHeight - 10); - is(panel.getBoundingClientRect().height, window.innerHeight - 10, "height is what we requested.") - // the arrow should not have moved. - var curArrowRect = arrow.getBoundingClientRect(); - is_close(curArrowRect.left, origArrowRect.left, "arrow should not have moved"); - is_close(curArrowRect.top, origArrowRect.top, "arrow should not have moved up or down"); - next(); + waitForPopupPositioned( + () => { panel.sizeTo(100, window.innerHeight - 10); }, + () => { + is(panel.getBoundingClientRect().height, window.innerHeight - 10, "height is what we requested.") + // the arrow should not have moved. + var curArrowRect = arrow.getBoundingClientRect(); + is_close(curArrowRect.left, origArrowRect.left, "arrow should not have moved"); + is_close(curArrowRect.top, origArrowRect.top, "arrow should not have moved up or down"); + next(); + }); }); }], @@ -317,13 +330,16 @@ var tests = [ var origArrowRect = arrow.getBoundingClientRect(); // Now size it such that the arrow can't be at either end of the panel but // instead somewhere in the middle as that is the only way things fit. - panel.sizeTo(100, window.innerHeight - 10); - is(panel.getBoundingClientRect().height, window.innerHeight - 10, "height is what we requested") - // the arrow should not have moved. - var curArrowRect = arrow.getBoundingClientRect(); - is_close(curArrowRect.left, origArrowRect.left, "arrow should not have moved"); - is_close(curArrowRect.top, origArrowRect.top, "arrow should not have moved up or down"); - next(); + waitForPopupPositioned( + () => { panel.sizeTo(100, window.innerHeight - 10); }, + () => { + is(panel.getBoundingClientRect().height, window.innerHeight - 10, "height is what we requested") + // the arrow should not have moved. + var curArrowRect = arrow.getBoundingClientRect(); + is_close(curArrowRect.left, origArrowRect.left, "arrow should not have moved"); + is_close(curArrowRect.top, origArrowRect.top, "arrow should not have moved up or down"); + next(); + }); }); }], diff --git a/toolkit/content/widgets/popup.xml b/toolkit/content/widgets/popup.xml index 6150907bad95..be7f6e0553dc 100644 --- a/toolkit/content/widgets/popup.xml +++ b/toolkit/content/widgets/popup.xml @@ -15,197 +15,6 @@ - - - - - - - return this.boxObject; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - null - - - - - - - - - - - - - - - - - false);