зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland. a=merge CLOSED TREE
This commit is contained in:
Коммит
04ab391b65
|
@ -70,6 +70,11 @@ function isHTMLElement(aNode) {
|
||||||
aNode.namespaceURI == "http://www.w3.org/1999/xhtml";
|
aNode.namespaceURI == "http://www.w3.org/1999/xhtml";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isXULElement(aNode) {
|
||||||
|
return aNode.nodeType == aNode.ELEMENT_NODE &&
|
||||||
|
aNode.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes the function when requested event is handled.
|
* Executes the function when requested event is handled.
|
||||||
*
|
*
|
||||||
|
@ -1092,18 +1097,19 @@ function synthClick(aNodeOrID, aCheckerOrEventSeq, aArgs) {
|
||||||
// Scroll the node into view, otherwise synth click may fail.
|
// Scroll the node into view, otherwise synth click may fail.
|
||||||
if (isHTMLElement(targetNode)) {
|
if (isHTMLElement(targetNode)) {
|
||||||
targetNode.scrollIntoView(true);
|
targetNode.scrollIntoView(true);
|
||||||
} else if (ChromeUtils.getClassName(targetNode) == "XULElement") {
|
} else if (isXULElement(targetNode)) {
|
||||||
var targetAcc = getAccessible(targetNode);
|
var targetAcc = getAccessible(targetNode);
|
||||||
targetAcc.scrollTo(SCROLL_TYPE_ANYWHERE);
|
targetAcc.scrollTo(SCROLL_TYPE_ANYWHERE);
|
||||||
}
|
}
|
||||||
|
|
||||||
var x = 1, y = 1;
|
var x = 1, y = 1;
|
||||||
if (aArgs && ("where" in aArgs) && aArgs.where == "right") {
|
if (aArgs && ("where" in aArgs) && aArgs.where == "right") {
|
||||||
if (isHTMLElement(targetNode))
|
if (isHTMLElement(targetNode)) {
|
||||||
x = targetNode.offsetWidth - 1;
|
x = targetNode.offsetWidth - 1;
|
||||||
else if (ChromeUtils.getClassName(targetNode) == "XULElement")
|
} else if (isXULElement(targetNode)) {
|
||||||
x = targetNode.boxObject.width - 1;
|
x = targetNode.boxObject.width - 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
synthesizeMouse(targetNode, x, y, aArgs ? aArgs : {});
|
synthesizeMouse(targetNode, x, y, aArgs ? aArgs : {});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,6 @@
|
||||||
PlacesCommandHook.updateBookmarkAllTabsCommand() -->
|
PlacesCommandHook.updateBookmarkAllTabsCommand() -->
|
||||||
<command id="Browser:BookmarkAllTabs"
|
<command id="Browser:BookmarkAllTabs"
|
||||||
oncommand="PlacesCommandHook.bookmarkPages(PlacesCommandHook.uniqueCurrentPages);"/>
|
oncommand="PlacesCommandHook.bookmarkPages(PlacesCommandHook.uniqueCurrentPages);"/>
|
||||||
<command id="Browser:Home" oncommand="BrowserHome();"/>
|
|
||||||
<command id="Browser:Back" oncommand="BrowserBack();" disabled="true"/>
|
<command id="Browser:Back" oncommand="BrowserBack();" disabled="true"/>
|
||||||
<command id="Browser:BackOrBackDuplicate" oncommand="BrowserBack(event);" disabled="true">
|
<command id="Browser:BackOrBackDuplicate" oncommand="BrowserBack(event);" disabled="true">
|
||||||
<observes element="Browser:Back" attribute="disabled"/>
|
<observes element="Browser:Back" attribute="disabled"/>
|
||||||
|
@ -202,7 +201,7 @@
|
||||||
<key id="goBackKb2" key="&goBackCmd.commandKey;" command="Browser:Back" modifiers="accel"/>
|
<key id="goBackKb2" key="&goBackCmd.commandKey;" command="Browser:Back" modifiers="accel"/>
|
||||||
<key id="goForwardKb2" key="&goForwardCmd.commandKey;" command="Browser:Forward" modifiers="accel"/>
|
<key id="goForwardKb2" key="&goForwardCmd.commandKey;" command="Browser:Forward" modifiers="accel"/>
|
||||||
#endif
|
#endif
|
||||||
<key id="goHome" keycode="VK_HOME" command="Browser:Home" modifiers="alt"/>
|
<key id="goHome" keycode="VK_HOME" oncommand="BrowserHome();" modifiers="alt"/>
|
||||||
<key keycode="VK_F5" command="Browser:Reload"/>
|
<key keycode="VK_F5" command="Browser:Reload"/>
|
||||||
#ifndef XP_MACOSX
|
#ifndef XP_MACOSX
|
||||||
<key id="showAllHistoryKb" key="&showAllHistoryCmd.commandkey;" command="Browser:ShowAllHistory" modifiers="accel,shift"/>
|
<key id="showAllHistoryKb" key="&showAllHistoryCmd.commandkey;" command="Browser:ShowAllHistory" modifiers="accel,shift"/>
|
||||||
|
|
|
@ -145,17 +145,17 @@ async function doSelectTests(contentType, content) {
|
||||||
is(selectPopup.children[1].getAttribute("label"), "One", "option label");
|
is(selectPopup.children[1].getAttribute("label"), "One", "option label");
|
||||||
|
|
||||||
EventUtils.synthesizeKey("KEY_ArrowDown");
|
EventUtils.synthesizeKey("KEY_ArrowDown");
|
||||||
is(menulist.menuBoxObject.activeChild, menulist.getItemAtIndex(2), "Select item 2");
|
is(menulist.activeChild, menulist.getItemAtIndex(2), "Select item 2");
|
||||||
is(menulist.selectedIndex, isWindows ? 2 : 1, "Select item 2 selectedIndex");
|
is(menulist.selectedIndex, isWindows ? 2 : 1, "Select item 2 selectedIndex");
|
||||||
|
|
||||||
EventUtils.synthesizeKey("KEY_ArrowDown");
|
EventUtils.synthesizeKey("KEY_ArrowDown");
|
||||||
is(menulist.menuBoxObject.activeChild, menulist.getItemAtIndex(3), "Select item 3");
|
is(menulist.activeChild, menulist.getItemAtIndex(3), "Select item 3");
|
||||||
is(menulist.selectedIndex, isWindows ? 3 : 1, "Select item 3 selectedIndex");
|
is(menulist.selectedIndex, isWindows ? 3 : 1, "Select item 3 selectedIndex");
|
||||||
|
|
||||||
EventUtils.synthesizeKey("KEY_ArrowDown");
|
EventUtils.synthesizeKey("KEY_ArrowDown");
|
||||||
|
|
||||||
// On Windows, one can navigate on disabled menuitems
|
// On Windows, one can navigate on disabled menuitems
|
||||||
is(menulist.menuBoxObject.activeChild, menulist.getItemAtIndex(9),
|
is(menulist.activeChild, menulist.getItemAtIndex(9),
|
||||||
"Skip optgroup header and disabled items select item 7");
|
"Skip optgroup header and disabled items select item 7");
|
||||||
is(menulist.selectedIndex, isWindows ? 9 : 1, "Select or skip disabled item selectedIndex");
|
is(menulist.selectedIndex, isWindows ? 9 : 1, "Select or skip disabled item selectedIndex");
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ async function doSelectTests(contentType, content) {
|
||||||
}
|
}
|
||||||
|
|
||||||
EventUtils.synthesizeKey("KEY_ArrowUp");
|
EventUtils.synthesizeKey("KEY_ArrowUp");
|
||||||
is(menulist.menuBoxObject.activeChild, menulist.getItemAtIndex(3), "Select item 3 again");
|
is(menulist.activeChild, menulist.getItemAtIndex(3), "Select item 3 again");
|
||||||
is(menulist.selectedIndex, isWindows ? 3 : 1, "Select item 3 selectedIndex");
|
is(menulist.selectedIndex, isWindows ? 3 : 1, "Select item 3 selectedIndex");
|
||||||
|
|
||||||
is((await getInputEvents()), 0, "Before closed - number of input events");
|
is((await getInputEvents()), 0, "Before closed - number of input events");
|
||||||
|
|
|
@ -8,8 +8,10 @@ add_task(async function() {
|
||||||
content.history.pushState({}, "2", "2.html");
|
content.history.pushState({}, "2", "2.html");
|
||||||
});
|
});
|
||||||
|
|
||||||
var backButton = document.getElementById("back-button");
|
await new Promise(resolve => SessionStore.getSessionHistory(gBrowser.selectedTab, resolve));
|
||||||
var rect = backButton.getBoundingClientRect();
|
|
||||||
|
let backButton = document.getElementById("back-button");
|
||||||
|
let rect = backButton.getBoundingClientRect();
|
||||||
|
|
||||||
info("waiting for the history menu to open");
|
info("waiting for the history menu to open");
|
||||||
|
|
||||||
|
|
|
@ -1246,14 +1246,14 @@ var UITour = {
|
||||||
showMenu(aWindow, aMenuName, aOpenCallback = null) {
|
showMenu(aWindow, aMenuName, aOpenCallback = null) {
|
||||||
log.debug("showMenu:", aMenuName);
|
log.debug("showMenu:", aMenuName);
|
||||||
function openMenuButton(aMenuBtn) {
|
function openMenuButton(aMenuBtn) {
|
||||||
if (!aMenuBtn || !aMenuBtn.boxObject || aMenuBtn.open) {
|
if (!aMenuBtn || !aMenuBtn.hasMenu() || aMenuBtn.open) {
|
||||||
if (aOpenCallback)
|
if (aOpenCallback)
|
||||||
aOpenCallback();
|
aOpenCallback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (aOpenCallback)
|
if (aOpenCallback)
|
||||||
aMenuBtn.addEventListener("popupshown", aOpenCallback, { once: true });
|
aMenuBtn.addEventListener("popupshown", aOpenCallback, { once: true });
|
||||||
aMenuBtn.boxObject.openMenu(true);
|
aMenuBtn.openMenu(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aMenuName == "appMenu" || aMenuName == "pageActionPanel") {
|
if (aMenuName == "appMenu" || aMenuName == "pageActionPanel") {
|
||||||
|
@ -1342,8 +1342,9 @@ var UITour = {
|
||||||
hideMenu(aWindow, aMenuName) {
|
hideMenu(aWindow, aMenuName) {
|
||||||
log.debug("hideMenu:", aMenuName);
|
log.debug("hideMenu:", aMenuName);
|
||||||
function closeMenuButton(aMenuBtn) {
|
function closeMenuButton(aMenuBtn) {
|
||||||
if (aMenuBtn && aMenuBtn.boxObject)
|
if (aMenuBtn && aMenuBtn.hasMenu()) {
|
||||||
aMenuBtn.boxObject.openMenu(false);
|
aMenuBtn.openMenu(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aMenuName == "appMenu") {
|
if (aMenuName == "appMenu") {
|
||||||
|
|
|
@ -1299,31 +1299,20 @@ CustomElementRegistry::CallGetCustomInterface(Element* aElement,
|
||||||
func->Call(aElement, iid, &customInterface);
|
func->Call(aElement, iid, &customInterface);
|
||||||
JS::Rooted<JSObject*> funcGlobal(RootingCx(), func->CallbackGlobalOrNull());
|
JS::Rooted<JSObject*> funcGlobal(RootingCx(), func->CallbackGlobalOrNull());
|
||||||
if (customInterface && funcGlobal) {
|
if (customInterface && funcGlobal) {
|
||||||
RefPtr<nsXPCWrappedJS> wrappedJS;
|
|
||||||
AutoJSAPI jsapi;
|
AutoJSAPI jsapi;
|
||||||
if (jsapi.Init(funcGlobal)) {
|
if (jsapi.Init(funcGlobal)) {
|
||||||
|
nsIXPConnect *xpConnect = nsContentUtils::XPConnect();
|
||||||
JSContext* cx = jsapi.cx();
|
JSContext* cx = jsapi.cx();
|
||||||
nsresult rv =
|
|
||||||
nsXPCWrappedJS::GetNewOrUsed(cx, customInterface,
|
|
||||||
NS_GET_IID(nsISupports),
|
|
||||||
getter_AddRefs(wrappedJS));
|
|
||||||
if (NS_SUCCEEDED(rv) && wrappedJS) {
|
|
||||||
// Check if the returned object implements the desired interface.
|
|
||||||
nsCOMPtr<nsISupports> retval;
|
|
||||||
if (NS_SUCCEEDED(wrappedJS->QueryInterface(aIID,
|
|
||||||
getter_AddRefs(retval)))) {
|
|
||||||
return retval.forget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, check if the element supports the interface directly, and just use that.
|
nsCOMPtr<nsISupports> wrapper;
|
||||||
nsCOMPtr<nsISupports> supports;
|
nsresult rv = xpConnect->WrapJSAggregatedToNative(aElement, cx, customInterface,
|
||||||
if (NS_SUCCEEDED(aElement->QueryInterface(aIID, getter_AddRefs(supports)))) {
|
aIID, getter_AddRefs(wrapper));
|
||||||
return supports.forget();
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
return wrapper.forget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -441,10 +441,7 @@ public:
|
||||||
* To allow native code to call methods of chrome-implemented custom elements,
|
* To allow native code to call methods of chrome-implemented custom elements,
|
||||||
* a helper method may be defined in the custom element called
|
* a helper method may be defined in the custom element called
|
||||||
* 'getCustomInterfaceCallback'. This method takes an IID and returns an
|
* 'getCustomInterfaceCallback'. This method takes an IID and returns an
|
||||||
* object which implements an XPCOM interface. If there is no
|
* object which implements an XPCOM interface.
|
||||||
* getCustomInterfaceCallback or the callback doesn't return an object,
|
|
||||||
* QueryInterface is called on aElement to see if this interface is
|
|
||||||
* implemented directly.
|
|
||||||
*
|
*
|
||||||
* This returns null if aElement is not from a chrome document.
|
* This returns null if aElement is not from a chrome document.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -259,7 +259,6 @@
|
||||||
#include "mozilla/dom/DocGroup.h"
|
#include "mozilla/dom/DocGroup.h"
|
||||||
#include "mozilla/dom/TabGroup.h"
|
#include "mozilla/dom/TabGroup.h"
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
#include "mozilla/dom/MenuBoxObject.h"
|
|
||||||
#include "mozilla/dom/TreeBoxObject.h"
|
#include "mozilla/dom/TreeBoxObject.h"
|
||||||
#include "nsIXULWindow.h"
|
#include "nsIXULWindow.h"
|
||||||
#include "nsXULCommandDispatcher.h"
|
#include "nsXULCommandDispatcher.h"
|
||||||
|
@ -6549,9 +6548,7 @@ nsIDocument::GetBoxObjectFor(Element* aElement, ErrorResult& aRv)
|
||||||
RefPtr<nsAtom> tag = BindingManager()->ResolveTag(aElement, &namespaceID);
|
RefPtr<nsAtom> tag = BindingManager()->ResolveTag(aElement, &namespaceID);
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
if (namespaceID == kNameSpaceID_XUL) {
|
if (namespaceID == kNameSpaceID_XUL) {
|
||||||
if (tag == nsGkAtoms::menu) {
|
if (tag == nsGkAtoms::tree) {
|
||||||
boxObject = new MenuBoxObject();
|
|
||||||
} else if (tag == nsGkAtoms::tree) {
|
|
||||||
boxObject = new TreeBoxObject();
|
boxObject = new TreeBoxObject();
|
||||||
} else {
|
} else {
|
||||||
boxObject = new BoxObject();
|
boxObject = new BoxObject();
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#include "mozilla/dom/HTMLEmbedElementBinding.h"
|
#include "mozilla/dom/HTMLEmbedElementBinding.h"
|
||||||
#include "mozilla/dom/XULElementBinding.h"
|
#include "mozilla/dom/XULElementBinding.h"
|
||||||
#include "mozilla/dom/XULFrameElementBinding.h"
|
#include "mozilla/dom/XULFrameElementBinding.h"
|
||||||
|
#include "mozilla/dom/XULMenuElementBinding.h"
|
||||||
#include "mozilla/dom/XULPopupElementBinding.h"
|
#include "mozilla/dom/XULPopupElementBinding.h"
|
||||||
#include "mozilla/dom/Promise.h"
|
#include "mozilla/dom/Promise.h"
|
||||||
#include "mozilla/dom/ResolveSystemBinding.h"
|
#include "mozilla/dom/ResolveSystemBinding.h"
|
||||||
|
@ -3861,6 +3862,9 @@ HTMLConstructor(JSContext* aCx, unsigned aArgc, JS::Value* aVp,
|
||||||
definition->mLocalName == nsGkAtoms::browser ||
|
definition->mLocalName == nsGkAtoms::browser ||
|
||||||
definition->mLocalName == nsGkAtoms::editor) {
|
definition->mLocalName == nsGkAtoms::editor) {
|
||||||
cb = XULFrameElement_Binding::GetConstructorObject;
|
cb = XULFrameElement_Binding::GetConstructorObject;
|
||||||
|
} else if (definition->mLocalName == nsGkAtoms::menu ||
|
||||||
|
definition->mLocalName == nsGkAtoms::menulist) {
|
||||||
|
cb = XULMenuElement_Binding::GetConstructorObject;
|
||||||
} else if (definition->mLocalName == nsGkAtoms::scrollbox) {
|
} else if (definition->mLocalName == nsGkAtoms::scrollbox) {
|
||||||
cb = XULScrollElement_Binding::GetConstructorObject;
|
cb = XULScrollElement_Binding::GetConstructorObject;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -5,10 +5,8 @@
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[Func="IsChromeOrXBL"]
|
[HTMLConstructor, Func="IsChromeOrXBL"]
|
||||||
interface MenuBoxObject : BoxObject {
|
interface XULMenuElement : XULElement {
|
||||||
|
|
||||||
void openMenu(boolean openFlag);
|
|
||||||
|
|
||||||
attribute Element? activeChild;
|
attribute Element? activeChild;
|
||||||
|
|
|
@ -50,6 +50,7 @@ WEBIDL_FILES = [
|
||||||
'WebExtensionContentScript.webidl',
|
'WebExtensionContentScript.webidl',
|
||||||
'WebExtensionPolicy.webidl',
|
'WebExtensionPolicy.webidl',
|
||||||
'XULFrameElement.webidl',
|
'XULFrameElement.webidl',
|
||||||
|
'XULMenuElement.webidl',
|
||||||
'XULScrollElement.webidl'
|
'XULScrollElement.webidl'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -665,8 +665,6 @@ var interfaceNamesInGlobalScope =
|
||||||
{name: "MediaStreamTrackEvent", insecureContext: true},
|
{name: "MediaStreamTrackEvent", insecureContext: true},
|
||||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||||
{name: "MediaStreamTrack", insecureContext: true},
|
{name: "MediaStreamTrack", insecureContext: true},
|
||||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
|
||||||
{name: "MenuBoxObject", insecureContext: true, xbl: true},
|
|
||||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||||
{name: "MessageChannel", insecureContext: true},
|
{name: "MessageChannel", insecureContext: true},
|
||||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||||
|
@ -1261,6 +1259,8 @@ var interfaceNamesInGlobalScope =
|
||||||
{name: "XULElement", insecureContext: true, xbl: true},
|
{name: "XULElement", insecureContext: true, xbl: true},
|
||||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||||
{name: "XULFrameElement", insecureContext: true, xbl: true},
|
{name: "XULFrameElement", insecureContext: true, xbl: true},
|
||||||
|
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||||
|
{name: "XULMenuElement", insecureContext: true, xbl: true},
|
||||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||||
{name: "XULPopupElement", insecureContext: true, xbl: true},
|
{name: "XULPopupElement", insecureContext: true, xbl: true},
|
||||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||||
|
|
|
@ -85,6 +85,14 @@ interface XULElement : Element {
|
||||||
|
|
||||||
[Constant]
|
[Constant]
|
||||||
readonly attribute CSSStyleDeclaration style;
|
readonly attribute CSSStyleDeclaration style;
|
||||||
|
|
||||||
|
// Returns true if this is a menu-type element that has a menu
|
||||||
|
// frame associated with it.
|
||||||
|
boolean hasMenu();
|
||||||
|
|
||||||
|
// If this is a menu-type element, opens or closes the menu
|
||||||
|
// depending on the argument passed.
|
||||||
|
void openMenu(boolean open);
|
||||||
};
|
};
|
||||||
|
|
||||||
XULElement implements GlobalEventHandlers;
|
XULElement implements GlobalEventHandlers;
|
||||||
|
|
|
@ -665,7 +665,6 @@ WEBIDL_FILES = [
|
||||||
'MediaTrackConstraintSet.webidl',
|
'MediaTrackConstraintSet.webidl',
|
||||||
'MediaTrackSettings.webidl',
|
'MediaTrackSettings.webidl',
|
||||||
'MediaTrackSupportedConstraints.webidl',
|
'MediaTrackSupportedConstraints.webidl',
|
||||||
'MenuBoxObject.webidl',
|
|
||||||
'MerchantValidationEvent.webidl',
|
'MerchantValidationEvent.webidl',
|
||||||
'MessageChannel.webidl',
|
'MessageChannel.webidl',
|
||||||
'MessageEvent.webidl',
|
'MessageEvent.webidl',
|
||||||
|
|
|
@ -4,9 +4,6 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "mozilla/dom/MenuBoxObject.h"
|
|
||||||
#include "mozilla/dom/MenuBoxObjectBinding.h"
|
|
||||||
|
|
||||||
#include "mozilla/dom/KeyboardEvent.h"
|
#include "mozilla/dom/KeyboardEvent.h"
|
||||||
#include "mozilla/dom/KeyboardEventBinding.h"
|
#include "mozilla/dom/KeyboardEventBinding.h"
|
||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
|
@ -15,49 +12,36 @@
|
||||||
#include "nsMenuBarListener.h"
|
#include "nsMenuBarListener.h"
|
||||||
#include "nsMenuFrame.h"
|
#include "nsMenuFrame.h"
|
||||||
#include "nsMenuPopupFrame.h"
|
#include "nsMenuPopupFrame.h"
|
||||||
|
#include "mozilla/dom/XULMenuElement.h"
|
||||||
|
#include "mozilla/dom/XULMenuElementBinding.h"
|
||||||
|
#include "nsXULPopupManager.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
MenuBoxObject::MenuBoxObject()
|
JSObject*
|
||||||
|
XULMenuElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||||
{
|
{
|
||||||
|
return XULMenuElement_Binding::Wrap(aCx, this, aGivenProto);
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuBoxObject::~MenuBoxObject()
|
nsIFrame*
|
||||||
|
XULMenuElement::GetFrame()
|
||||||
{
|
{
|
||||||
|
nsCOMPtr<nsIContent> kungFuDeathGrip = this; // keep a reference
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDocument> doc = GetUncomposedDoc();
|
||||||
|
if (doc) {
|
||||||
|
doc->FlushPendingNotifications(FlushType::Frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject* MenuBoxObject::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
return GetPrimaryFrame();
|
||||||
{
|
|
||||||
return MenuBoxObject_Binding::Wrap(aCx, this, aGivenProto);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuBoxObject::OpenMenu(bool aOpenFlag)
|
|
||||||
{
|
|
||||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
|
||||||
if (pm) {
|
|
||||||
nsIFrame* frame = GetFrame(false);
|
|
||||||
if (frame) {
|
|
||||||
if (aOpenFlag) {
|
|
||||||
nsCOMPtr<nsIContent> content = mContent;
|
|
||||||
pm->ShowMenu(content, false, false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
nsMenuFrame* menu = do_QueryFrame(frame);
|
|
||||||
if (menu) {
|
|
||||||
nsMenuPopupFrame* popupFrame = menu->GetPopup();
|
|
||||||
if (popupFrame)
|
|
||||||
pm->HidePopup(popupFrame->GetContent(), false, true, false, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<Element>
|
already_AddRefed<Element>
|
||||||
MenuBoxObject::GetActiveChild()
|
XULMenuElement::GetActiveChild()
|
||||||
{
|
{
|
||||||
nsMenuFrame* menu = do_QueryFrame(GetFrame(false));
|
nsMenuFrame* menu = do_QueryFrame(GetFrame());
|
||||||
if (menu) {
|
if (menu) {
|
||||||
RefPtr<Element> el;
|
RefPtr<Element> el;
|
||||||
menu->GetActiveChild(getter_AddRefs(el));
|
menu->GetActiveChild(getter_AddRefs(el));
|
||||||
|
@ -66,15 +50,17 @@ MenuBoxObject::GetActiveChild()
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuBoxObject::SetActiveChild(Element* arg)
|
void
|
||||||
|
XULMenuElement::SetActiveChild(Element* arg)
|
||||||
{
|
{
|
||||||
nsMenuFrame* menu = do_QueryFrame(GetFrame(false));
|
nsMenuFrame* menu = do_QueryFrame(GetFrame());
|
||||||
if (menu) {
|
if (menu) {
|
||||||
menu->SetActiveChild(arg);
|
menu->SetActiveChild(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MenuBoxObject::HandleKeyPress(KeyboardEvent& keyEvent)
|
bool
|
||||||
|
XULMenuElement::HandleKeyPress(KeyboardEvent& keyEvent)
|
||||||
{
|
{
|
||||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||||
if (!pm) {
|
if (!pm) {
|
||||||
|
@ -89,7 +75,7 @@ bool MenuBoxObject::HandleKeyPress(KeyboardEvent& keyEvent)
|
||||||
if (nsMenuBarListener::IsAccessKeyPressed(&keyEvent))
|
if (nsMenuBarListener::IsAccessKeyPressed(&keyEvent))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
nsMenuFrame* menu = do_QueryFrame(GetFrame(false));
|
nsMenuFrame* menu = do_QueryFrame(GetFrame());
|
||||||
if (!menu) {
|
if (!menu) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -115,9 +101,10 @@ bool MenuBoxObject::HandleKeyPress(KeyboardEvent& keyEvent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MenuBoxObject::OpenedWithKey()
|
bool
|
||||||
|
XULMenuElement::OpenedWithKey()
|
||||||
{
|
{
|
||||||
nsMenuFrame* menuframe = do_QueryFrame(GetFrame(false));
|
nsMenuFrame* menuframe = do_QueryFrame(GetFrame());
|
||||||
if (!menuframe) {
|
if (!menuframe) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_dom_XULMenuElement_h
|
||||||
|
#define mozilla_dom_XULMenuElement_h
|
||||||
|
|
||||||
|
#include "nsXULElement.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
class KeyboardEvent;
|
||||||
|
|
||||||
|
class XULMenuElement final : public nsXULElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit XULMenuElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
|
||||||
|
: nsXULElement(aNodeInfo)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_CAN_RUN_SCRIPT already_AddRefed<Element> GetActiveChild();
|
||||||
|
MOZ_CAN_RUN_SCRIPT void SetActiveChild(Element* arg);
|
||||||
|
MOZ_CAN_RUN_SCRIPT bool HandleKeyPress(KeyboardEvent& keyEvent);
|
||||||
|
MOZ_CAN_RUN_SCRIPT bool OpenedWithKey();
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual ~XULMenuElement() {}
|
||||||
|
JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) final;
|
||||||
|
|
||||||
|
nsIFrame* GetFrame();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // XULMenuElement_h
|
|
@ -23,6 +23,7 @@ if CONFIG['MOZ_XUL']:
|
||||||
|
|
||||||
EXPORTS.mozilla.dom += [
|
EXPORTS.mozilla.dom += [
|
||||||
'XULFrameElement.h',
|
'XULFrameElement.h',
|
||||||
|
'XULMenuElement.h',
|
||||||
'XULPopupElement.h',
|
'XULPopupElement.h',
|
||||||
'XULScrollElement.h',
|
'XULScrollElement.h',
|
||||||
]
|
]
|
||||||
|
@ -38,6 +39,7 @@ if CONFIG['MOZ_XUL']:
|
||||||
'nsXULSortService.cpp',
|
'nsXULSortService.cpp',
|
||||||
'XULDocument.cpp',
|
'XULDocument.cpp',
|
||||||
'XULFrameElement.cpp',
|
'XULFrameElement.cpp',
|
||||||
|
'XULMenuElement.cpp',
|
||||||
'XULPopupElement.cpp',
|
'XULPopupElement.cpp',
|
||||||
'XULScrollElement.cpp',
|
'XULScrollElement.cpp',
|
||||||
]
|
]
|
||||||
|
|
|
@ -75,6 +75,7 @@
|
||||||
#include "nsICSSDeclaration.h"
|
#include "nsICSSDeclaration.h"
|
||||||
#include "nsLayoutUtils.h"
|
#include "nsLayoutUtils.h"
|
||||||
#include "XULFrameElement.h"
|
#include "XULFrameElement.h"
|
||||||
|
#include "XULMenuElement.h"
|
||||||
#include "XULPopupElement.h"
|
#include "XULPopupElement.h"
|
||||||
#include "XULScrollElement.h"
|
#include "XULScrollElement.h"
|
||||||
|
|
||||||
|
@ -159,6 +160,12 @@ nsXULElement* nsXULElement::Construct(already_AddRefed<mozilla::dom::NodeInfo>&&
|
||||||
return new XULFrameElement(frameni);
|
return new XULFrameElement(frameni);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nodeInfo->Equals(nsGkAtoms::menu) ||
|
||||||
|
nodeInfo->Equals(nsGkAtoms::menulist)) {
|
||||||
|
already_AddRefed<mozilla::dom::NodeInfo> menuni = nodeInfo.forget();
|
||||||
|
return new XULMenuElement(menuni);
|
||||||
|
}
|
||||||
|
|
||||||
if (nodeInfo->Equals(nsGkAtoms::scrollbox)) {
|
if (nodeInfo->Equals(nsGkAtoms::scrollbox)) {
|
||||||
already_AddRefed<mozilla::dom::NodeInfo> scrollni = nodeInfo.forget();
|
already_AddRefed<mozilla::dom::NodeInfo> scrollni = nodeInfo.forget();
|
||||||
return new XULScrollElement(scrollni);
|
return new XULScrollElement(scrollni);
|
||||||
|
@ -304,7 +311,17 @@ NS_IMPL_RELEASE_INHERITED(nsXULElement, nsStyledElement)
|
||||||
|
|
||||||
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsXULElement)
|
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsXULElement)
|
||||||
NS_ELEMENT_INTERFACE_TABLE_TO_MAP_SEGUE
|
NS_ELEMENT_INTERFACE_TABLE_TO_MAP_SEGUE
|
||||||
NS_INTERFACE_MAP_END_INHERITING(nsStyledElement)
|
|
||||||
|
nsCOMPtr<nsISupports> iface =
|
||||||
|
CustomElementRegistry::CallGetCustomInterface(this, aIID);
|
||||||
|
if (iface) {
|
||||||
|
iface->QueryInterface(aIID, aInstancePtr);
|
||||||
|
if (*aInstancePtr) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_END_INHERITING(Element)
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// nsINode interface
|
// nsINode interface
|
||||||
|
@ -496,6 +513,39 @@ nsXULElement::IsFocusableInternal(int32_t *aTabIndex, bool aWithMouse)
|
||||||
return shouldFocus;
|
return shouldFocus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsXULElement::HasMenu()
|
||||||
|
{
|
||||||
|
nsMenuFrame* menu = do_QueryFrame(GetPrimaryFrame());
|
||||||
|
return menu != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsXULElement::OpenMenu(bool aOpenFlag)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIDocument> doc = GetUncomposedDoc();
|
||||||
|
if (doc) {
|
||||||
|
doc->FlushPendingNotifications(FlushType::Frames);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||||
|
if (pm) {
|
||||||
|
if (aOpenFlag) {
|
||||||
|
// Nothing will happen if this element isn't a menu.
|
||||||
|
pm->ShowMenu(this, false, false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nsMenuFrame* menu = do_QueryFrame(GetPrimaryFrame());
|
||||||
|
if (menu) {
|
||||||
|
nsMenuPopupFrame* popupFrame = menu->GetPopup();
|
||||||
|
if (popupFrame) {
|
||||||
|
pm->HidePopup(popupFrame->GetContent(), false, true, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
nsXULElement::PerformAccesskey(bool aKeyCausesActivation,
|
nsXULElement::PerformAccesskey(bool aKeyCausesActivation,
|
||||||
bool aIsTrustedEvent)
|
bool aIsTrustedEvent)
|
||||||
|
|
|
@ -375,6 +375,9 @@ public:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool HasMenu();
|
||||||
|
MOZ_CAN_RUN_SCRIPT void OpenMenu(bool aOpenFlag);
|
||||||
|
|
||||||
virtual bool PerformAccesskey(bool aKeyCausesActivation,
|
virtual bool PerformAccesskey(bool aKeyCausesActivation,
|
||||||
bool aIsTrustedEvent) override;
|
bool aIsTrustedEvent) override;
|
||||||
void ClickWithInputSource(uint16_t aInputSource, bool aIsTrustedEvent);
|
void ClickWithInputSource(uint16_t aInputSource, bool aIsTrustedEvent);
|
||||||
|
|
|
@ -334,9 +334,11 @@ MacOSFontEntry::GetVariationAxes(nsTArray<gfxFontVariationAxis>& aVariationAxes)
|
||||||
kCTFontVariationAxisNameKey);
|
kCTFontVariationAxisNameKey);
|
||||||
if (name) {
|
if (name) {
|
||||||
CFIndex len = CFStringGetLength(name);
|
CFIndex len = CFStringGetLength(name);
|
||||||
axis.mName.SetLength(len);
|
nsAutoString nameStr;
|
||||||
|
nameStr.SetLength(len);
|
||||||
CFStringGetCharacters(name, CFRangeMake(0, len),
|
CFStringGetCharacters(name, CFRangeMake(0, len),
|
||||||
(UniChar*)axis.mName.BeginWriting());
|
(UniChar*)nameStr.BeginWriting());
|
||||||
|
AppendUTF16toUTF8(nameStr, axis.mName);
|
||||||
}
|
}
|
||||||
axis.mTag = (uint32_t)tag;
|
axis.mTag = (uint32_t)tag;
|
||||||
axis.mMinValue = minValue;
|
axis.mMinValue = minValue;
|
||||||
|
|
|
@ -351,17 +351,29 @@ template<typename Tok> JS::Result<Ok>
|
||||||
BinASTParser<Tok>::checkPositionalParameterIndices(Handle<GCVector<JSAtom*>> positionalParams,
|
BinASTParser<Tok>::checkPositionalParameterIndices(Handle<GCVector<JSAtom*>> positionalParams,
|
||||||
ListNode* params)
|
ListNode* params)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(positionalParams.get().length() == params->count());
|
#ifdef DEBUG
|
||||||
|
// positionalParams should have the same length as non-rest parameters.
|
||||||
|
size_t paramsCount = params->count();
|
||||||
|
if (paramsCount > 0) {
|
||||||
|
if (params->last()->isKind(ParseNodeKind::Spread)) {
|
||||||
|
paramsCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(positionalParams.get().length() == paramsCount);
|
||||||
|
#endif
|
||||||
|
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
for (ParseNode* param : params->contents()) {
|
for (ParseNode* param : params->contents()) {
|
||||||
if (param->isKind(ParseNodeKind::Assign)) {
|
if (param->isKind(ParseNodeKind::Assign)) {
|
||||||
param = param->as<AssignmentNode>().left();
|
param = param->as<AssignmentNode>().left();
|
||||||
}
|
}
|
||||||
|
if (param->isKind(ParseNodeKind::Spread)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(param->isKind(ParseNodeKind::Name) ||
|
MOZ_ASSERT(param->isKind(ParseNodeKind::Name) ||
|
||||||
param->isKind(ParseNodeKind::Object) ||
|
param->isKind(ParseNodeKind::Object) ||
|
||||||
param->isKind(ParseNodeKind::Array) ||
|
param->isKind(ParseNodeKind::Array));
|
||||||
param->isKind(ParseNodeKind::Spread));
|
|
||||||
|
|
||||||
if (JSAtom* name = positionalParams.get()[i]) {
|
if (JSAtom* name = positionalParams.get()[i]) {
|
||||||
// Simple or default parameter.
|
// Simple or default parameter.
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
var g = newGlobal();
|
||||||
|
var w1 = g.Math;
|
||||||
|
var w2 = g.evaluate("new Array");
|
||||||
|
recomputeWrappers(this, g);
|
||||||
|
recomputeWrappers();
|
|
@ -6137,6 +6137,46 @@ NukeAllCCWs(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
RecomputeWrappers(JSContext* cx, unsigned argc, Value* vp)
|
||||||
|
{
|
||||||
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
|
||||||
|
if (args.length() > 2) {
|
||||||
|
JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr, JSSMSG_INVALID_ARGS,
|
||||||
|
"recomputeWrappers");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Compartment* sourceComp = nullptr;
|
||||||
|
if (args.get(0).isObject()) {
|
||||||
|
sourceComp = GetObjectCompartment(UncheckedUnwrap(&args[0].toObject()));
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Compartment* targetComp = nullptr;
|
||||||
|
if (args.get(1).isObject()) {
|
||||||
|
targetComp = GetObjectCompartment(UncheckedUnwrap(&args[1].toObject()));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SingleOrAllCompartments final : public CompartmentFilter {
|
||||||
|
JS::Compartment* comp;
|
||||||
|
explicit SingleOrAllCompartments(JS::Compartment* c) : comp(c) {}
|
||||||
|
virtual bool match(JS::Compartment* c) const override {
|
||||||
|
return !comp || comp == c;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!js::RecomputeWrappers(cx,
|
||||||
|
SingleOrAllCompartments(sourceComp),
|
||||||
|
SingleOrAllCompartments(targetComp)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
args.rval().setUndefined();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
GetMaxArgs(JSContext* cx, unsigned argc, Value* vp)
|
GetMaxArgs(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
|
@ -8196,6 +8236,12 @@ JS_FN_HELP("parseBin", BinParse, 1, 0,
|
||||||
"nukeAllCCWs()",
|
"nukeAllCCWs()",
|
||||||
" Like nukeCCW, but for all CrossCompartmentWrappers targeting the current compartment."),
|
" Like nukeCCW, but for all CrossCompartmentWrappers targeting the current compartment."),
|
||||||
|
|
||||||
|
JS_FN_HELP("recomputeWrappers", RecomputeWrappers, 2, 0,
|
||||||
|
"recomputeWrappers([src, [target]])",
|
||||||
|
" Recompute all cross-compartment wrappers. src and target are both optional\n"
|
||||||
|
" and can be used to filter source or target compartments: the unwrapped\n"
|
||||||
|
" object's compartment is used as CompartmentFilter.\n"),
|
||||||
|
|
||||||
JS_FN_HELP("wrapWithProto", WrapWithProto, 2, 0,
|
JS_FN_HELP("wrapWithProto", WrapWithProto, 2, 0,
|
||||||
"wrapWithProto(obj)",
|
"wrapWithProto(obj)",
|
||||||
" Wrap an object into a noop wrapper with prototype semantics."),
|
" Wrap an object into a noop wrapper with prototype semantics."),
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_MenuBoxObject_h
|
|
||||||
#define mozilla_dom_MenuBoxObject_h
|
|
||||||
|
|
||||||
#include "mozilla/dom/BoxObject.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class KeyboardEvent;
|
|
||||||
|
|
||||||
class MenuBoxObject final : public BoxObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
MenuBoxObject();
|
|
||||||
|
|
||||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
|
||||||
|
|
||||||
void OpenMenu(bool aOpenFlag);
|
|
||||||
already_AddRefed<Element> GetActiveChild();
|
|
||||||
void SetActiveChild(Element* arg);
|
|
||||||
bool HandleKeyPress(KeyboardEvent& keyEvent);
|
|
||||||
bool OpenedWithKey();
|
|
||||||
|
|
||||||
private:
|
|
||||||
~MenuBoxObject();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_MenuBoxObject_h
|
|
|
@ -31,7 +31,6 @@ EXPORTS += [
|
||||||
|
|
||||||
EXPORTS.mozilla.dom += [
|
EXPORTS.mozilla.dom += [
|
||||||
'BoxObject.h',
|
'BoxObject.h',
|
||||||
'MenuBoxObject.h',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
|
@ -54,7 +53,6 @@ UNIFIED_SOURCES += [
|
||||||
|
|
||||||
if CONFIG['MOZ_XUL']:
|
if CONFIG['MOZ_XUL']:
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
'MenuBoxObject.cpp',
|
|
||||||
'nsDeckFrame.cpp',
|
'nsDeckFrame.cpp',
|
||||||
'nsDocElementBoxFrame.cpp',
|
'nsDocElementBoxFrame.cpp',
|
||||||
'nsGroupBoxFrame.cpp',
|
'nsGroupBoxFrame.cpp',
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "nsDisplayList.h"
|
#include "nsDisplayList.h"
|
||||||
#include "nsContainerFrame.h"
|
#include "nsContainerFrame.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
|
#include "nsXULPopupManager.h"
|
||||||
|
|
||||||
#ifdef ACCESSIBILITY
|
#ifdef ACCESSIBILITY
|
||||||
#include "nsAccessibilityService.h"
|
#include "nsAccessibilityService.h"
|
||||||
|
|
|
@ -64,7 +64,7 @@ nsReflowFrameRunnable::Run()
|
||||||
// Creates a new Toolbar frame and returns it
|
// Creates a new Toolbar frame and returns it
|
||||||
//
|
//
|
||||||
nsIFrame*
|
nsIFrame*
|
||||||
NS_NewProgressMeterFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle)
|
NS_NewProgressMeterFrame (nsIPresShell* aPresShell, mozilla::ComputedStyle* aStyle)
|
||||||
{
|
{
|
||||||
return new (aPresShell) nsProgressMeterFrame(aStyle);
|
return new (aPresShell) nsProgressMeterFrame(aStyle);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ job-defaults:
|
||||||
require-build: true
|
require-build: true
|
||||||
worker-type:
|
worker-type:
|
||||||
by-platform:
|
by-platform:
|
||||||
linux64.*: releng-hardware/gecko-t-linux-talos
|
linux64.*: releng-hardware/gecko-t-linux-talos-tw
|
||||||
worker:
|
worker:
|
||||||
by-platform:
|
by-platform:
|
||||||
linux64.*:
|
linux64.*:
|
||||||
|
|
|
@ -1008,7 +1008,7 @@ def set_worker_type(config, tests):
|
||||||
elif test_platform.startswith('linux') or test_platform.startswith('android'):
|
elif test_platform.startswith('linux') or test_platform.startswith('android'):
|
||||||
if test.get('suite', '') in ['talos', 'raptor'] and \
|
if test.get('suite', '') in ['talos', 'raptor'] and \
|
||||||
not test['build-platform'].startswith('linux64-ccov'):
|
not test['build-platform'].startswith('linux64-ccov'):
|
||||||
test['worker-type'] = 'releng-hardware/gecko-t-linux-talos'
|
test['worker-type'] = 'releng-hardware/gecko-t-linux-talos-tw'
|
||||||
else:
|
else:
|
||||||
test['worker-type'] = LINUX_WORKER_TYPES[test['instance-size']]
|
test['worker-type'] = LINUX_WORKER_TYPES[test['instance-size']]
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -36,7 +36,7 @@ WORKER_TYPES = {
|
||||||
'aws-provisioner-v1/taskcluster-generic': ('docker-worker', 'linux'),
|
'aws-provisioner-v1/taskcluster-generic': ('docker-worker', 'linux'),
|
||||||
'invalid/invalid': ('invalid', None),
|
'invalid/invalid': ('invalid', None),
|
||||||
'invalid/always-optimized': ('always-optimized', None),
|
'invalid/always-optimized': ('always-optimized', None),
|
||||||
'releng-hardware/gecko-t-linux-talos': ('native-engine', 'linux'),
|
'releng-hardware/gecko-t-linux-talos-tw': ('native-engine', 'linux'),
|
||||||
'scriptworker-prov-v1/balrog-dev': ('balrog', None),
|
'scriptworker-prov-v1/balrog-dev': ('balrog', None),
|
||||||
'scriptworker-prov-v1/balrogworker-v1': ('balrog', None),
|
'scriptworker-prov-v1/balrogworker-v1': ('balrog', None),
|
||||||
'scriptworker-prov-v1/beetmoverworker-v1': ('beetmover', None),
|
'scriptworker-prov-v1/beetmoverworker-v1': ('beetmover', None),
|
||||||
|
|
|
@ -110,9 +110,8 @@ class MozXULElement extends XULElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicate that a class defining an element implements one or more
|
* Indicate that a class defining a XUL element implements one or more
|
||||||
* XPCOM interfaces. The custom element getCustomInterface is added
|
* XPCOM interfaces by adding a getCustomInterface implementation to it.
|
||||||
* as well as an implementation of QueryInterface.
|
|
||||||
*
|
*
|
||||||
* The supplied class should implement the properties and methods of
|
* The supplied class should implement the properties and methods of
|
||||||
* all of the interfaces that are specified.
|
* all of the interfaces that are specified.
|
||||||
|
@ -120,10 +119,9 @@ class MozXULElement extends XULElement {
|
||||||
* @param cls
|
* @param cls
|
||||||
* The class that implements the interface.
|
* The class that implements the interface.
|
||||||
* @param names
|
* @param names
|
||||||
* Array of interface names
|
* Array of interface names.
|
||||||
*/
|
*/
|
||||||
static implementCustomInterface(cls, ifaces) {
|
static implementCustomInterface(cls, ifaces) {
|
||||||
cls.prototype.QueryInterface = ChromeUtils.generateQI(ifaces);
|
|
||||||
cls.prototype.getCustomInterfaceCallback = function getCustomInterfaceCallback(iface) {
|
cls.prototype.getCustomInterfaceCallback = function getCustomInterfaceCallback(iface) {
|
||||||
if (ifaces.includes(Ci[Components.interfacesByID[iface.number]])) {
|
if (ifaces.includes(Ci[Components.interfacesByID[iface.number]])) {
|
||||||
return getInterfaceProxy(this);
|
return getInterfaceProxy(this);
|
||||||
|
|
|
@ -29,7 +29,7 @@ function runTests() {
|
||||||
gMenuPopup = document.getElementById("thepopup");
|
gMenuPopup = document.getElementById("thepopup");
|
||||||
gTrigger = document.getElementById("trigger");
|
gTrigger = document.getElementById("trigger");
|
||||||
|
|
||||||
gIsMenu = gTrigger.boxObject instanceof MenuBoxObject;
|
gIsMenu = gTrigger.hasMenu();
|
||||||
|
|
||||||
// a hacky way to get the screen position of the document. Cache the event
|
// a hacky way to get the screen position of the document. Cache the event
|
||||||
// so that we can use it in calls to openPopup.
|
// so that we can use it in calls to openPopup.
|
||||||
|
|
|
@ -106,7 +106,7 @@ function menuTests()
|
||||||
is(gContextMenuFired, true, "context menu fired when menu open");
|
is(gContextMenuFired, true, "context menu fired when menu open");
|
||||||
|
|
||||||
gSelectionStep = 1;
|
gSelectionStep = 1;
|
||||||
$("menu").boxObject.activeChild = $("menu2");
|
$("menu").activeChild = $("menu2");
|
||||||
synthesizeMouse(element, 0, 0, { type : "contextmenu", button: 0 });
|
synthesizeMouse(element, 0, 0, { type : "contextmenu", button: 0 });
|
||||||
|
|
||||||
$("menu").open = false;
|
$("menu").open = false;
|
||||||
|
|
|
@ -12,7 +12,10 @@
|
||||||
<!-- test results are displayed in the html:body -->
|
<!-- test results are displayed in the html:body -->
|
||||||
<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
|
<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
|
||||||
|
|
||||||
<simpleelement id="simple"/>
|
<button id="one"/>
|
||||||
|
<simpleelement id="two" style="-moz-user-focus: normal;"/>
|
||||||
|
<simpleelement id="three" disabled="true" style="-moz-user-focus: normal;"/>
|
||||||
|
<button id="four"/>
|
||||||
|
|
||||||
<!-- test code goes here -->
|
<!-- test code goes here -->
|
||||||
<script type="application/javascript"><![CDATA[
|
<script type="application/javascript"><![CDATA[
|
||||||
|
@ -22,7 +25,7 @@
|
||||||
async function runTests() {
|
async function runTests() {
|
||||||
ok(MozXULElement, "MozXULElement defined on the window");
|
ok(MozXULElement, "MozXULElement defined on the window");
|
||||||
testParseXULToFragment();
|
testParseXULToFragment();
|
||||||
testCustomInterface();
|
await testCustomInterface();
|
||||||
|
|
||||||
let htmlWin = await new Promise(resolve => {
|
let htmlWin = await new Promise(resolve => {
|
||||||
let htmlIframe = document.createElement("iframe");
|
let htmlIframe = document.createElement("iframe");
|
||||||
|
@ -51,29 +54,37 @@
|
||||||
deck.remove();
|
deck.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCustomInterface() {
|
async function testCustomInterface() {
|
||||||
class SimpleElement extends MozXULElement {
|
class SimpleElement extends MozXULElement {
|
||||||
get disabled() {
|
get disabled() {
|
||||||
return false;
|
return this.getAttribute("disabled") == "true";
|
||||||
}
|
}
|
||||||
|
|
||||||
set disabled(val) {
|
set disabled(val) {
|
||||||
|
if (val) this.setAttribute("disabled", "true");
|
||||||
|
else this.removeAttribute("disabled");
|
||||||
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
get tabIndex() {
|
get tabIndex() {
|
||||||
return 0;
|
return parseInt(this.getAttribute("tabIndex")) || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
set tabIndex(val) {
|
set tabIndex(val) {
|
||||||
|
if (val) this.setAttribute("tabIndex", val);
|
||||||
|
else this.removeAttribute("tabIndex");
|
||||||
|
return val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("simpleelement", SimpleElement);
|
|
||||||
MozXULElement.implementCustomInterface(SimpleElement, [Ci.nsIDOMXULControlElement]);
|
MozXULElement.implementCustomInterface(SimpleElement, [Ci.nsIDOMXULControlElement]);
|
||||||
|
customElements.define("simpleelement", SimpleElement);
|
||||||
|
|
||||||
|
let twoElement = document.getElementById("two");
|
||||||
|
|
||||||
is(document.documentElement.getCustomInterfaceCallback, undefined,
|
is(document.documentElement.getCustomInterfaceCallback, undefined,
|
||||||
"No getCustomInterfaceCallback on non-custom element");
|
"No getCustomInterfaceCallback on non-custom element");
|
||||||
is(typeof document.getElementById("simple").getCustomInterfaceCallback, "function",
|
is(typeof twoElement.getCustomInterfaceCallback, "function",
|
||||||
"getCustomInterfaceCallback available on custom element when set");
|
"getCustomInterfaceCallback available on custom element when set");
|
||||||
try {
|
try {
|
||||||
document.documentElement.QueryInterface(Ci.nsIDOMXULControlElement)
|
document.documentElement.QueryInterface(Ci.nsIDOMXULControlElement)
|
||||||
|
@ -81,8 +92,41 @@
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
ok(true, "Non-custom element implements custom interface");
|
ok(true, "Non-custom element implements custom interface");
|
||||||
}
|
}
|
||||||
ok(document.getElementById("simple").QueryInterface(Ci.nsIDOMXULControlElement),
|
|
||||||
"Implements custom interface");
|
// Try various ways to get the custom interface.
|
||||||
|
|
||||||
|
let asControl = twoElement.getCustomInterfaceCallback(Ci.nsIDOMXULControlElement);
|
||||||
|
ok(asControl, twoElement, "getCustomInterface returns interface implementation ");
|
||||||
|
|
||||||
|
asControl = twoElement.QueryInterface(Ci.nsIDOMXULControlElement);
|
||||||
|
ok(asControl, "QueryInterface to nsIDOMXULControlElement");
|
||||||
|
ok(asControl instanceof Node, "Control is a Node");
|
||||||
|
|
||||||
|
// Now make sure that the custom element handles focus/tabIndex as needed by shitfing
|
||||||
|
// focus around and enabling/disabling the simple elements.
|
||||||
|
|
||||||
|
// Enable Full Keyboard Access emulation on Mac
|
||||||
|
await SpecialPowers.pushPrefEnv({"set": [["accessibility.tabfocus", 7]]});
|
||||||
|
|
||||||
|
ok(!twoElement.disabled, "two is enabled");
|
||||||
|
ok(document.getElementById("three").disabled, "three is disabled");
|
||||||
|
|
||||||
|
await SimpleTest.promiseFocus();
|
||||||
|
ok(document.hasFocus(), "has focus");
|
||||||
|
|
||||||
|
// This should skip the disabled simpleelement.
|
||||||
|
synthesizeKey("VK_TAB");
|
||||||
|
is(document.activeElement.id, "one", "Tab 1");
|
||||||
|
synthesizeKey("VK_TAB");
|
||||||
|
is(document.activeElement.id, "two", "Tab 2");
|
||||||
|
synthesizeKey("VK_TAB");
|
||||||
|
is(document.activeElement.id, "four", "Tab 3");
|
||||||
|
|
||||||
|
twoElement.disabled = true;
|
||||||
|
is(twoElement.getAttribute("disabled"), "true", "two disabled after change");
|
||||||
|
|
||||||
|
synthesizeKey("VK_TAB", { shiftKey: true });
|
||||||
|
is(document.activeElement.id, "one", "Tab 1");
|
||||||
}
|
}
|
||||||
]]>
|
]]>
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -218,7 +218,7 @@ function test_menulist_open(element, scroller)
|
||||||
|
|
||||||
synthesizeMouse(element.menupopup.childNodes[1], 2, 2, { type: "mousemove" });
|
synthesizeMouse(element.menupopup.childNodes[1], 2, 2, { type: "mousemove" });
|
||||||
synthesizeMouse(element.menupopup.childNodes[1], 6, 6, { type: "mousemove" });
|
synthesizeMouse(element.menupopup.childNodes[1], 6, 6, { type: "mousemove" });
|
||||||
is(element.menuBoxObject.activeChild, item, "activeChild after menu highlight " + element.id);
|
is(element.activeChild, item, "activeChild after menu highlight " + element.id);
|
||||||
is(element.selectedIndex, 0, "selectedIndex after menu highlight " + element.id);
|
is(element.selectedIndex, 0, "selectedIndex after menu highlight " + element.id);
|
||||||
is(scroller.scrollTop, 0, "scroll position after menu highlight " + element.id);
|
is(scroller.scrollTop, 0, "scroll position after menu highlight " + element.id);
|
||||||
|
|
||||||
|
|
|
@ -60,11 +60,11 @@ function runTests()
|
||||||
keyCheck(list, "KEY_ArrowUp", iswin ? 1 : 4, 1, "cursor up wrap");
|
keyCheck(list, "KEY_ArrowUp", iswin ? 1 : 4, 1, "cursor up wrap");
|
||||||
|
|
||||||
list.selectedIndex = 4;
|
list.selectedIndex = 4;
|
||||||
list.menuBoxObject.activeChild = list.selectedItem;
|
list.activeChild = list.selectedItem;
|
||||||
keyCheck(list, "KEY_ArrowDown", iswin ? 4 : 1, 4, "cursor down wrap");
|
keyCheck(list, "KEY_ArrowDown", iswin ? 4 : 1, 4, "cursor down wrap");
|
||||||
|
|
||||||
list.selectedIndex = 0;
|
list.selectedIndex = 0;
|
||||||
list.menuBoxObject.activeChild = list.selectedItem;
|
list.activeChild = list.selectedItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that attempting to open the menulist does not change the selection
|
// check that attempting to open the menulist does not change the selection
|
||||||
|
@ -171,7 +171,7 @@ function tabAndScroll()
|
||||||
var item = list.getItemAtIndex(10);
|
var item = list.getItemAtIndex(10);
|
||||||
var originalPosition = item.getBoundingClientRect().top;
|
var originalPosition = item.getBoundingClientRect().top;
|
||||||
|
|
||||||
list.menuBoxObject.activeChild = item;
|
list.activeChild = item;
|
||||||
ok(item.getBoundingClientRect().top < originalPosition,
|
ok(item.getBoundingClientRect().top < originalPosition,
|
||||||
"position of item 1: " + item.getBoundingClientRect().top + " -> " + originalPosition);
|
"position of item 1: " + item.getBoundingClientRect().top + " -> " + originalPosition);
|
||||||
|
|
||||||
|
@ -257,15 +257,15 @@ function checkCursorNavigation()
|
||||||
|
|
||||||
// Check whether cursor up and down wraps.
|
// Check whether cursor up and down wraps.
|
||||||
list.selectedIndex = 0;
|
list.selectedIndex = 0;
|
||||||
list.menuBoxObject.activeChild = list.selectedItem;
|
list.activeChild = list.selectedItem;
|
||||||
synthesizeKey("KEY_ArrowUp");
|
synthesizeKey("KEY_ArrowUp");
|
||||||
is(list.menuBoxObject.activeChild,
|
is(list.activeChild,
|
||||||
document.getElementById(iswin || ismac ? "b1" : "b4"), "cursor up wrap while open");
|
document.getElementById(iswin || ismac ? "b1" : "b4"), "cursor up wrap while open");
|
||||||
|
|
||||||
list.selectedIndex = 3;
|
list.selectedIndex = 3;
|
||||||
list.menuBoxObject.activeChild = list.selectedItem;
|
list.activeChild = list.selectedItem;
|
||||||
synthesizeKey("KEY_ArrowDown");
|
synthesizeKey("KEY_ArrowDown");
|
||||||
is(list.menuBoxObject.activeChild,
|
is(list.activeChild,
|
||||||
document.getElementById(iswin || ismac ? "b4" : "b1"), "cursor down wrap while open");
|
document.getElementById(iswin || ismac ? "b4" : "b1"), "cursor down wrap while open");
|
||||||
|
|
||||||
synthesizeKey("KEY_ArrowUp", {altKey: true});
|
synthesizeKey("KEY_ArrowUp", {altKey: true});
|
||||||
|
|
|
@ -124,7 +124,7 @@ function runTest()
|
||||||
function menulistShown()
|
function menulistShown()
|
||||||
{
|
{
|
||||||
let menulist = document.getElementById(test.list);
|
let menulist = document.getElementById(test.list);
|
||||||
is(menulist.menuBoxObject.activeChild.label, menulist.getItemAtIndex(test.initial).label, test.list + " initial selection");
|
is(menulist.activeChild.label, menulist.getItemAtIndex(test.initial).label, test.list + " initial selection");
|
||||||
|
|
||||||
let cs = window.getComputedStyle(menulist.menupopup);
|
let cs = window.getComputedStyle(menulist.menupopup);
|
||||||
let bpTop = parseFloat(cs.paddingTop) + parseFloat(cs.borderTopWidth);
|
let bpTop = parseFloat(cs.paddingTop) + parseFloat(cs.borderTopWidth);
|
||||||
|
@ -138,12 +138,12 @@ function menulistShown()
|
||||||
|
|
||||||
for (let i = 0; i < test.downs.length; i++) {
|
for (let i = 0; i < test.downs.length; i++) {
|
||||||
sendKey("PAGE_DOWN");
|
sendKey("PAGE_DOWN");
|
||||||
is(menulist.menuBoxObject.activeChild.label, menulist.getItemAtIndex(test.downs[i]).label, test.list + " page down " + i);
|
is(menulist.activeChild.label, menulist.getItemAtIndex(test.downs[i]).label, test.list + " page down " + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < test.ups.length; i++) {
|
for (let i = 0; i < test.ups.length; i++) {
|
||||||
sendKey("PAGE_UP");
|
sendKey("PAGE_UP");
|
||||||
is(menulist.menuBoxObject.activeChild.label, menulist.getItemAtIndex(test.ups[i]).label, test.list + " page up " + i);
|
is(menulist.activeChild.label, menulist.getItemAtIndex(test.ups[i]).label, test.list + " page up " + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
menulist.open = false;
|
menulist.open = false;
|
||||||
|
|
|
@ -252,11 +252,9 @@ function goNextStepSync() {
|
||||||
function openMenu(menu) {
|
function openMenu(menu) {
|
||||||
if ("open" in menu) {
|
if ("open" in menu) {
|
||||||
menu.open = true;
|
menu.open = true;
|
||||||
|
} else if (menu.hasMenu()) {
|
||||||
|
menu.openMenu(true);
|
||||||
} else {
|
} else {
|
||||||
var bo = menu.boxObject;
|
|
||||||
if (bo instanceof MenuBoxObject)
|
|
||||||
bo.openMenu(true);
|
|
||||||
else
|
|
||||||
synthesizeMouse(menu, 4, 4, { });
|
synthesizeMouse(menu, 4, 4, { });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,11 +262,9 @@ function openMenu(menu) {
|
||||||
function closeMenu(menu, popup) {
|
function closeMenu(menu, popup) {
|
||||||
if ("open" in menu) {
|
if ("open" in menu) {
|
||||||
menu.open = false;
|
menu.open = false;
|
||||||
|
} else if (menu.hasMenu()) {
|
||||||
|
menu.openMenu(false);
|
||||||
} else {
|
} else {
|
||||||
var bo = menu.boxObject;
|
|
||||||
if (bo instanceof MenuBoxObject)
|
|
||||||
bo.openMenu(false);
|
|
||||||
else
|
|
||||||
popup.hidePopup();
|
popup.hidePopup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -291,7 +287,7 @@ function checkOpen(menuid, testname) {
|
||||||
var menu = document.getElementById(menuid);
|
var menu = document.getElementById(menuid);
|
||||||
if ("open" in menu)
|
if ("open" in menu)
|
||||||
ok(menu.open, testname + " " + menuid + " menu is open");
|
ok(menu.open, testname + " " + menuid + " menu is open");
|
||||||
else if (menu.boxObject instanceof MenuBoxObject)
|
else if (menu.hasMenu())
|
||||||
ok(menu.getAttribute("open") == "true", testname + " " + menuid + " menu is open");
|
ok(menu.getAttribute("open") == "true", testname + " " + menuid + " menu is open");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,7 +295,7 @@ function checkClosed(menuid, testname) {
|
||||||
var menu = document.getElementById(menuid);
|
var menu = document.getElementById(menuid);
|
||||||
if ("open" in menu)
|
if ("open" in menu)
|
||||||
ok(!menu.open, testname + " " + menuid + " menu is open");
|
ok(!menu.open, testname + " " + menuid + " menu is open");
|
||||||
else if (menu.boxObject instanceof MenuBoxObject)
|
else if (menu.hasMenu())
|
||||||
ok(!menu.hasAttribute("open"), testname + " " + menuid + " menu is closed");
|
ok(!menu.hasAttribute("open"), testname + " " + menuid + " menu is closed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
|
|
||||||
<property name="open" onget="return this.hasAttribute('open');">
|
<property name="open" onget="return this.hasAttribute('open');">
|
||||||
<setter><![CDATA[
|
<setter><![CDATA[
|
||||||
if (this.boxObject instanceof MenuBoxObject) {
|
if (this.hasMenu()) {
|
||||||
this.boxObject.openMenu(val);
|
this.openMenu(val);
|
||||||
} else if (val) {
|
} else if (val) {
|
||||||
// Fall back to just setting the attribute
|
// Fall back to just setting the attribute
|
||||||
this.setAttribute("open", "true");
|
this.setAttribute("open", "true");
|
||||||
|
@ -128,7 +128,7 @@
|
||||||
|
|
||||||
<handler event="keypress">
|
<handler event="keypress">
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
if (this.boxObject instanceof MenuBoxObject) {
|
if (this.hasMenu()) {
|
||||||
if (this.open)
|
if (this.open)
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -48,17 +48,11 @@
|
||||||
<implementation implements="nsIDOMXULContainerElement">
|
<implementation implements="nsIDOMXULContainerElement">
|
||||||
<property name="open" onget="return this.hasAttribute('open');">
|
<property name="open" onget="return this.hasAttribute('open');">
|
||||||
<setter><![CDATA[
|
<setter><![CDATA[
|
||||||
this.boxObject.openMenu(val);
|
this.openMenu(val);
|
||||||
return val;
|
return val;
|
||||||
]]></setter>
|
]]></setter>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
<property name="openedWithKey" readonly="true">
|
|
||||||
<getter><![CDATA[
|
|
||||||
return this.boxObject.openedWithKey;
|
|
||||||
]]></getter>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<!-- nsIDOMXULContainerElement interface -->
|
<!-- nsIDOMXULContainerElement interface -->
|
||||||
<method name="appendItem">
|
<method name="appendItem">
|
||||||
<parameter name="aLabel"/>
|
<parameter name="aLabel"/>
|
||||||
|
|
|
@ -29,11 +29,11 @@
|
||||||
<handler event="popupshowing">
|
<handler event="popupshowing">
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
if (event.target.parentNode == this) {
|
if (event.target.parentNode == this) {
|
||||||
this.menuBoxObject.activeChild = null;
|
this.activeChild = null;
|
||||||
if (this.selectedItem)
|
if (this.selectedItem)
|
||||||
// Not ready for auto-setting the active child in hierarchies yet.
|
// Not ready for auto-setting the active child in hierarchies yet.
|
||||||
// For now, only do this when the outermost menupopup opens.
|
// For now, only do this when the outermost menupopup opens.
|
||||||
this.menuBoxObject.activeChild = this.mSelectedInternal;
|
this.activeChild = this.mSelectedInternal;
|
||||||
}
|
}
|
||||||
]]>
|
]]>
|
||||||
</handler>
|
</handler>
|
||||||
|
@ -50,9 +50,9 @@
|
||||||
event.keyCode == KeyEvent.DOM_VK_BACK_SPACE ||
|
event.keyCode == KeyEvent.DOM_VK_BACK_SPACE ||
|
||||||
event.charCode > 0)) {
|
event.charCode > 0)) {
|
||||||
// Moving relative to an item: start from the currently selected item
|
// Moving relative to an item: start from the currently selected item
|
||||||
this.menuBoxObject.activeChild = this.mSelectedInternal;
|
this.activeChild = this.mSelectedInternal;
|
||||||
if (this.menuBoxObject.handleKeyPress(event)) {
|
if (this.handleKeyPress(event)) {
|
||||||
this.menuBoxObject.activeChild.doCommand();
|
this.activeChild.doCommand();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,6 @@
|
||||||
<constructor>
|
<constructor>
|
||||||
this.mSelectedInternal = null;
|
this.mSelectedInternal = null;
|
||||||
this.mAttributeObserver = null;
|
this.mAttributeObserver = null;
|
||||||
this.menuBoxObject = this.boxObject;
|
|
||||||
this.setInitialSelection();
|
this.setInitialSelection();
|
||||||
</constructor>
|
</constructor>
|
||||||
|
|
||||||
|
@ -121,8 +120,7 @@
|
||||||
<property name="description" onset="this.setAttribute('description',val); return val;"
|
<property name="description" onset="this.setAttribute('description',val); return val;"
|
||||||
onget="return this.getAttribute('description');"/>
|
onget="return this.getAttribute('description');"/>
|
||||||
|
|
||||||
<property name="open" onset="this.menuBoxObject.openMenu(val);
|
<property name="open" onset="this.openMenu(val); return val;"
|
||||||
return val;"
|
|
||||||
onget="return this.hasAttribute('open');"/>
|
onget="return this.hasAttribute('open');"/>
|
||||||
|
|
||||||
<property name="itemCount" readonly="true"
|
<property name="itemCount" readonly="true"
|
||||||
|
|
|
@ -432,7 +432,7 @@ function populateChildren(menulist, options, selectedIndex, zoom,
|
||||||
// may have been removed from the selected item. Since that's normally only
|
// may have been removed from the selected item. Since that's normally only
|
||||||
// set for the initially selected on popupshowing for the menulist, and we
|
// set for the initially selected on popupshowing for the menulist, and we
|
||||||
// don't want to close and re-open the popup, we manually set it here.
|
// don't want to close and re-open the popup, we manually set it here.
|
||||||
menulist.menuBoxObject.activeChild = item;
|
menulist.activeChild = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
item.setAttribute("value", option.index);
|
item.setAttribute("value", option.index);
|
||||||
|
@ -471,7 +471,7 @@ function populateChildren(menulist, options, selectedIndex, zoom,
|
||||||
searchbox.blur();
|
searchbox.blur();
|
||||||
if (searchbox.nextElementSibling.localName == "menuitem" &&
|
if (searchbox.nextElementSibling.localName == "menuitem" &&
|
||||||
!searchbox.nextElementSibling.hidden) {
|
!searchbox.nextElementSibling.hidden) {
|
||||||
menulist.menuBoxObject.activeChild = searchbox.nextElementSibling;
|
menulist.activeChild = searchbox.nextElementSibling;
|
||||||
} else {
|
} else {
|
||||||
var currentOption = searchbox.nextElementSibling;
|
var currentOption = searchbox.nextElementSibling;
|
||||||
while (currentOption && (currentOption.localName != "menuitem" ||
|
while (currentOption && (currentOption.localName != "menuitem" ||
|
||||||
|
@ -479,7 +479,7 @@ function populateChildren(menulist, options, selectedIndex, zoom,
|
||||||
currentOption = currentOption.nextElementSibling;
|
currentOption = currentOption.nextElementSibling;
|
||||||
}
|
}
|
||||||
if (currentOption) {
|
if (currentOption) {
|
||||||
menulist.menuBoxObject.activeChild = currentOption;
|
menulist.activeChild = currentOption;
|
||||||
} else {
|
} else {
|
||||||
searchbox.focus();
|
searchbox.focus();
|
||||||
}
|
}
|
||||||
|
@ -556,7 +556,7 @@ function onSearchInput() {
|
||||||
function onSearchFocus() {
|
function onSearchFocus() {
|
||||||
let searchObj = this;
|
let searchObj = this;
|
||||||
let menupopup = searchObj.parentElement;
|
let menupopup = searchObj.parentElement;
|
||||||
menupopup.parentElement.menuBoxObject.activeChild = null;
|
menupopup.parentElement.activeChild = null;
|
||||||
menupopup.setAttribute("ignorekeys", "true");
|
menupopup.setAttribute("ignorekeys", "true");
|
||||||
currentBrowser.messageManager.sendAsyncMessage("Forms:SearchFocused", {});
|
currentBrowser.messageManager.sendAsyncMessage("Forms:SearchFocused", {});
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче