Merge mozilla-central to autoland. a=merge CLOSED TREE

This commit is contained in:
Narcis Beleuzu 2018-09-19 19:44:24 +03:00
Родитель dea8a7e3af 49ae56e475
Коммит 04ab391b65
42 изменённых файлов: 338 добавлений и 198 удалений

Просмотреть файл

@ -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,17 +1097,18 @@ 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,33 +1299,22 @@ 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, nsCOMPtr<nsISupports> wrapper;
NS_GET_IID(nsISupports), nsresult rv = xpConnect->WrapJSAggregatedToNative(aElement, cx, customInterface,
getter_AddRefs(wrappedJS)); aIID, getter_AddRefs(wrapper));
if (NS_SUCCEEDED(rv) && wrappedJS) { if (NS_SUCCEEDED(rv)) {
// Check if the returned object implements the desired interface. return wrapper.forget();
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> supports;
if (NS_SUCCEEDED(aElement->QueryInterface(aIID, getter_AddRefs(supports)))) {
return supports.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
JSObject* MenuBoxObject::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) nsCOMPtr<nsIDocument> doc = GetUncomposedDoc();
{ if (doc) {
return MenuBoxObject_Binding::Wrap(aCx, this, aGivenProto); doc->FlushPendingNotifications(FlushType::Frames);
}
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);
}
}
}
} }
return GetPrimaryFrame();
} }
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;
} }

41
dom/xul/XULMenuElement.h Normal file
Просмотреть файл

@ -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,20 +257,20 @@ 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});
is(list.open, ismac, "alt+up closes popup"); is(list.open, ismac, "alt+up closes popup");
if (ismac) { if (ismac) {
list.open = false; list.open = false;
} }

Просмотреть файл

@ -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,24 +252,20 @@ 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; synthesizeMouse(menu, 4, 4, { });
if (bo instanceof MenuBoxObject)
bo.openMenu(true);
else
synthesizeMouse(menu, 4, 4, { });
} }
} }
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; popup.hidePopup();
if (bo instanceof MenuBoxObject)
bo.openMenu(false);
else
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", {});
} }