mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1204187 - IonMonkey: MIPS32: Inline RelocationIterator. r=nbp (b97e654314) - Bug 1182607, use the right rectangle for a popup anchored at a rectangle when determining if the mouse click was over the anchor, r=tn (e1f3d04aa6) - Bug 1186972, use correct coordinates when comparing mouse position with menu anchor rectangle so that select element popups close properly, r=tn (271a0de264) - Bug 1177000, only consider popups of the same type when determining whether a popup shouldn't reopen, this allows dropdown buttons in popup to reopen properly, r=neil (a56095be88) - Bug 1149745, on Windows, menulist should select the value when the cursor keys are used to navigate items, r=neil (18afefe5b0)
This commit is contained in:
@@ -51,9 +51,11 @@
|
||||
gQueue.push(new synthDownKey("ml_tangerine", new focusChecker("ml_marmalade")));
|
||||
gQueue.push(new synthEscapeKey("ml_marmalade", new focusChecker("menulist")));
|
||||
if (!MAC) {
|
||||
gQueue.push(new synthDownKey("menulist", new nofocusChecker("ml_marmalade")));
|
||||
gQueue.push(new synthOpenComboboxKey("menulist", new focusChecker("ml_marmalade")));
|
||||
gQueue.push(new synthEnterKey("ml_marmalade", new focusChecker("menulist")));
|
||||
// On Windows, items get selected during navigation.
|
||||
let expectedItem = WIN ? "ml_tangerine" : "ml_marmalade";
|
||||
gQueue.push(new synthDownKey("menulist", new nofocusChecker(expectedItem)));
|
||||
gQueue.push(new synthOpenComboboxKey("menulist", new focusChecker(expectedItem)));
|
||||
gQueue.push(new synthEnterKey(expectedItem, new focusChecker("menulist")));
|
||||
} else {
|
||||
todo(false, "Bug 746531 - timeouts of last three menulist tests on OS X");
|
||||
}
|
||||
@@ -73,7 +75,7 @@ if (!MAC) {
|
||||
gQueue.push(new changeCurrentItem("listbox", "lb_item1"));
|
||||
gQueue.push(new changeCurrentItem("richlistbox", "rlb_item1"));
|
||||
if (!MAC) {
|
||||
gQueue.push(new changeCurrentItem("menulist", "ml_tangerine"));
|
||||
gQueue.push(new changeCurrentItem("menulist", WIN ? "ml_marmalade" : "ml_tangerine"));
|
||||
}
|
||||
gQueue.push(new changeCurrentItem("emenulist", "eml_tangerine"));
|
||||
|
||||
|
||||
@@ -112,29 +112,6 @@ AssemblerMIPSShared::asAsm()
|
||||
return *static_cast<Assembler*>(this);
|
||||
}
|
||||
|
||||
class RelocationIterator
|
||||
{
|
||||
CompactBufferReader reader_;
|
||||
// offset in bytes
|
||||
uint32_t offset_;
|
||||
|
||||
public:
|
||||
RelocationIterator(CompactBufferReader& reader)
|
||||
: reader_(reader)
|
||||
{ }
|
||||
|
||||
bool read() {
|
||||
if (!reader_.more())
|
||||
return false;
|
||||
offset_ = reader_.readUnsigned();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t offset() const {
|
||||
return offset_;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
AssemblerMIPSShared::copyJumpRelocationTable(uint8_t* dest)
|
||||
{
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
|
||||
#include "jit/mips32/Assembler-mips32.h"
|
||||
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
||||
using mozilla::DebugOnly;
|
||||
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
||||
@@ -171,9 +175,8 @@ CodeFromJump(Instruction* jump)
|
||||
void
|
||||
Assembler::TraceJumpRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader)
|
||||
{
|
||||
RelocationIterator iter(reader);
|
||||
while (iter.read()) {
|
||||
JitCode* child = CodeFromJump((Instruction*)(code->raw() + iter.offset()));
|
||||
while (reader.more()) {
|
||||
JitCode* child = CodeFromJump((Instruction*)(code->raw() + reader.readUnsigned()));
|
||||
TraceManuallyBarrieredEdge(trc, &child, "rel32");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,7 +319,8 @@ private:
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarFrame::ChangeMenuItem(nsMenuFrame* aMenuItem,
|
||||
bool aSelectFirstItem)
|
||||
bool aSelectFirstItem,
|
||||
bool aFromKey)
|
||||
{
|
||||
if (mCurrentMenu == aMenuItem)
|
||||
return NS_OK;
|
||||
|
||||
@@ -35,7 +35,9 @@ public:
|
||||
virtual nsMenuFrame* GetCurrentMenuItem() override;
|
||||
NS_IMETHOD SetCurrentMenuItem(nsMenuFrame* aMenuItem) override;
|
||||
virtual void CurrentMenuIsBeingDestroyed() override;
|
||||
NS_IMETHOD ChangeMenuItem(nsMenuFrame* aMenuItem, bool aSelectFirstItem) override;
|
||||
NS_IMETHOD ChangeMenuItem(nsMenuFrame* aMenuItem,
|
||||
bool aSelectFirstItem,
|
||||
bool aFromKey) override;
|
||||
|
||||
NS_IMETHOD SetActive(bool aActiveFlag) override;
|
||||
|
||||
|
||||
@@ -474,7 +474,7 @@ nsMenuFrame::HandleEvent(nsPresContext* aPresContext,
|
||||
// Submenus don't get closed up immediately.
|
||||
}
|
||||
else if (this == menuParent->GetCurrentMenuItem()) {
|
||||
menuParent->ChangeMenuItem(nullptr, false);
|
||||
menuParent->ChangeMenuItem(nullptr, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -487,7 +487,7 @@ nsMenuFrame::HandleEvent(nsPresContext* aPresContext,
|
||||
}
|
||||
|
||||
// Let the menu parent know we're the new item.
|
||||
menuParent->ChangeMenuItem(this, false);
|
||||
menuParent->ChangeMenuItem(this, false, false);
|
||||
NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
|
||||
NS_ENSURE_TRUE(menuParent, NS_OK);
|
||||
|
||||
@@ -1432,7 +1432,7 @@ nsMenuFrame::SetActiveChild(nsIDOMElement* aChild)
|
||||
|
||||
if (!aChild) {
|
||||
// Remove the current selection
|
||||
popupFrame->ChangeMenuItem(nullptr, false);
|
||||
popupFrame->ChangeMenuItem(nullptr, false, false);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -1440,7 +1440,7 @@ nsMenuFrame::SetActiveChild(nsIDOMElement* aChild)
|
||||
|
||||
nsMenuFrame* menu = do_QueryFrame(child->GetPrimaryFrame());
|
||||
if (menu)
|
||||
popupFrame->ChangeMenuItem(menu, false);
|
||||
popupFrame->ChangeMenuItem(menu, false, false);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,11 @@ public:
|
||||
// new item aMenuItem. For a menubar, if another menu is already open, the
|
||||
// new menu aMenuItem is opened. In this case, if aSelectFirstItem is true,
|
||||
// select the first item in it. For menupopups, the menu is not opened and
|
||||
// the aSelectFirstItem argument is not used.
|
||||
NS_IMETHOD ChangeMenuItem(nsMenuFrame* aMenuItem, bool aSelectFirstItem) = 0;
|
||||
// the aSelectFirstItem argument is not used. The aFromKey argument indicates
|
||||
// that the keyboard was used to navigate to the new menu item.
|
||||
NS_IMETHOD ChangeMenuItem(nsMenuFrame* aMenuItem,
|
||||
bool aSelectFirstItem,
|
||||
bool aFromKey) = 0;
|
||||
|
||||
// returns true if the menupopup is open. For menubars, returns false.
|
||||
virtual bool IsOpen() = 0;
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "nsThemeConstants.h"
|
||||
#include "nsTransitionManager.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsIDOMXULSelectCntrlItemEl.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/EventStateManager.h"
|
||||
#include "mozilla/EventStates.h"
|
||||
@@ -1746,7 +1747,7 @@ void nsMenuPopupFrame::ChangeByPage(bool aIsUp)
|
||||
|
||||
// Select the new menuitem.
|
||||
if (newMenu) {
|
||||
ChangeMenuItem(newMenu, false);
|
||||
ChangeMenuItem(newMenu, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1777,7 +1778,8 @@ nsMenuPopupFrame::CurrentMenuIsBeingDestroyed()
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMenuPopupFrame::ChangeMenuItem(nsMenuFrame* aMenuItem,
|
||||
bool aSelectFirstItem)
|
||||
bool aSelectFirstItem,
|
||||
bool aFromKey)
|
||||
{
|
||||
if (mCurrentMenu == aMenuItem)
|
||||
return NS_OK;
|
||||
@@ -1804,6 +1806,26 @@ nsMenuPopupFrame::ChangeMenuItem(nsMenuFrame* aMenuItem,
|
||||
if (aMenuItem) {
|
||||
EnsureMenuItemIsVisible(aMenuItem);
|
||||
aMenuItem->SelectMenu(true);
|
||||
|
||||
// On Windows, a menulist should update its value whenever navigation was
|
||||
// done by the keyboard.
|
||||
#ifdef XP_WIN
|
||||
if (aFromKey && IsOpen()) {
|
||||
nsIFrame* parentMenu = GetParent();
|
||||
if (parentMenu) {
|
||||
nsCOMPtr<nsIDOMXULMenuListElement> menulist = do_QueryInterface(parentMenu->GetContent());
|
||||
if (menulist) {
|
||||
// Fire a command event as the new item, but we don't want to close
|
||||
// the menu, blink it, or update any other state of the menuitem. The
|
||||
// command event will cause the item to be selected.
|
||||
nsContentUtils::DispatchXULCommand(aMenuItem->GetContent(),
|
||||
nsContentUtils::IsCallerChrome(),
|
||||
nullptr, PresContext()->PresShell(),
|
||||
false, false, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
mCurrentMenu = aMenuItem;
|
||||
|
||||
@@ -171,7 +171,9 @@ public:
|
||||
virtual nsMenuFrame* GetCurrentMenuItem() override;
|
||||
NS_IMETHOD SetCurrentMenuItem(nsMenuFrame* aMenuItem) override;
|
||||
virtual void CurrentMenuIsBeingDestroyed() override;
|
||||
NS_IMETHOD ChangeMenuItem(nsMenuFrame* aMenuItem, bool aSelectFirstItem) override;
|
||||
NS_IMETHOD ChangeMenuItem(nsMenuFrame* aMenuItem,
|
||||
bool aSelectFirstItem,
|
||||
bool aFromKey) override;
|
||||
|
||||
// as popups are opened asynchronously, the popup pending state is used to
|
||||
// prevent multiple requests from attempting to open the same popup twice
|
||||
@@ -388,9 +390,9 @@ public:
|
||||
// Return the anchor if there is one.
|
||||
nsIContent* GetAnchor() const { return mAnchorContent; }
|
||||
|
||||
// Return the screen coordinates of the popup, or (-1, -1) if anchored.
|
||||
// This position is in CSS pixels.
|
||||
nsIntPoint ScreenPosition() const { return mScreenRect.TopLeft(); }
|
||||
// Return the screen coordinates in CSS pixels of the popup,
|
||||
// or (-1, -1, 0, 0) if anchored.
|
||||
nsIntRect GetScreenAnchorRect() const { return mScreenRect; }
|
||||
|
||||
nsIntPoint GetLastClientOffset() const { return mLastClientOffset; }
|
||||
|
||||
|
||||
@@ -188,17 +188,26 @@ nsXULPopupManager::Rollup(uint32_t aCount, bool aFlush,
|
||||
nsMenuChainItem* item = GetTopVisibleMenu();
|
||||
if (item) {
|
||||
if (aLastRolledUp) {
|
||||
// we need to get the popup that will be closed last, so that
|
||||
// widget can keep track of it so it doesn't reopen if a mouse
|
||||
// down event is going to processed.
|
||||
// Keep going up the menu chain to get the first level menu. This will
|
||||
// be the one that closes up last. It's possible that this menu doesn't
|
||||
// end up closing because the popuphiding event was cancelled, but in
|
||||
// that case we don't need to deal with the menu reopening as it will
|
||||
// already still be open.
|
||||
// We need to get the popup that will be closed last, so that widget can
|
||||
// keep track of it so it doesn't reopen if a mousedown event is going to
|
||||
// processed. Keep going up the menu chain to get the first level menu of
|
||||
// the same type. If a different type is encountered it means we have,
|
||||
// for example, a menulist or context menu inside a panel, and we want to
|
||||
// treat these as distinct. It's possible that this menu doesn't end up
|
||||
// closing because the popuphiding event was cancelled, but in that case
|
||||
// we don't need to deal with the menu reopening as it will already still
|
||||
// be open.
|
||||
nsMenuChainItem* first = item;
|
||||
while (first->GetParent())
|
||||
first = first->GetParent();
|
||||
while (first->GetParent()) {
|
||||
nsMenuChainItem* parent = first->GetParent();
|
||||
if (first->Frame()->PopupType() != parent->Frame()->PopupType() ||
|
||||
first->IsContextMenu() != parent->IsContextMenu()) {
|
||||
break;
|
||||
}
|
||||
first = parent;
|
||||
}
|
||||
|
||||
|
||||
*aLastRolledUp = first->Content();
|
||||
}
|
||||
|
||||
@@ -218,38 +227,52 @@ nsXULPopupManager::Rollup(uint32_t aCount, bool aFlush,
|
||||
// when the click was over the anchor. This way, clicking on a menu doesn't
|
||||
// reopen the menu.
|
||||
if ((consumeResult == ConsumeOutsideClicks_ParentOnly || noRollupOnAnchor) && pos) {
|
||||
nsCOMPtr<nsIContent> anchor = item->Frame()->GetAnchor();
|
||||
nsMenuPopupFrame* popupFrame = item->Frame();
|
||||
nsIntRect anchorRect;
|
||||
if (popupFrame->IsAnchored()) {
|
||||
// Check if the popup has a screen anchor rectangle. If not, get the rectangle
|
||||
// from the anchor element.
|
||||
anchorRect = popupFrame->GetScreenAnchorRect();
|
||||
if (anchorRect.x == -1 || anchorRect.y == -1) {
|
||||
nsCOMPtr<nsIContent> anchor = popupFrame->GetAnchor();
|
||||
|
||||
// Check if the anchor has indicated another node to use for checking
|
||||
// for roll-up. That way, we can anchor a popup on anonymous content or
|
||||
// an individual icon, while clicking elsewhere within a button or other
|
||||
// container doesn't result in us re-opening the popup.
|
||||
if (anchor) {
|
||||
nsAutoString consumeAnchor;
|
||||
anchor->GetAttr(kNameSpaceID_None, nsGkAtoms::consumeanchor,
|
||||
consumeAnchor);
|
||||
if (!consumeAnchor.IsEmpty()) {
|
||||
nsIDocument* doc = anchor->GetOwnerDocument();
|
||||
nsIContent* newAnchor = doc->GetElementById(consumeAnchor);
|
||||
if (newAnchor) {
|
||||
anchor = newAnchor;
|
||||
// Check if the anchor has indicated another node to use for checking
|
||||
// for roll-up. That way, we can anchor a popup on anonymous content or
|
||||
// an individual icon, while clicking elsewhere within a button or other
|
||||
// container doesn't result in us re-opening the popup.
|
||||
if (anchor) {
|
||||
nsAutoString consumeAnchor;
|
||||
anchor->GetAttr(kNameSpaceID_None, nsGkAtoms::consumeanchor,
|
||||
consumeAnchor);
|
||||
if (!consumeAnchor.IsEmpty()) {
|
||||
nsIDocument* doc = anchor->GetOwnerDocument();
|
||||
nsIContent* newAnchor = doc->GetElementById(consumeAnchor);
|
||||
if (newAnchor) {
|
||||
anchor = newAnchor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (anchor && anchor->GetPrimaryFrame()) {
|
||||
anchorRect = anchor->GetPrimaryFrame()->GetScreenRect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (anchor && anchor->GetPrimaryFrame()) {
|
||||
// It's possible that some other element is above the anchor at the same
|
||||
// position, but the only thing that would happen is that the mouse
|
||||
// event will get consumed, so here only a quick coordinates check is
|
||||
// done rather than a slower complete check of what is at that location.
|
||||
if (anchor->GetPrimaryFrame()->GetScreenRect().Contains(*pos)) {
|
||||
if (consumeResult == ConsumeOutsideClicks_ParentOnly) {
|
||||
consume = true;
|
||||
}
|
||||
// It's possible that some other element is above the anchor at the same
|
||||
// position, but the only thing that would happen is that the mouse
|
||||
// event will get consumed, so here only a quick coordinates check is
|
||||
// done rather than a slower complete check of what is at that location.
|
||||
nsPresContext* presContext = item->Frame()->PresContext();
|
||||
nsIntPoint posCSSPixels(presContext->DevPixelsToIntCSSPixels(pos->x),
|
||||
presContext->DevPixelsToIntCSSPixels(pos->y));
|
||||
if (anchorRect.Contains(posCSSPixels)) {
|
||||
if (consumeResult == ConsumeOutsideClicks_ParentOnly) {
|
||||
consume = true;
|
||||
}
|
||||
|
||||
if (noRollupOnAnchor) {
|
||||
rollup = false;
|
||||
}
|
||||
if (noRollupOnAnchor) {
|
||||
rollup = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1987,7 +2010,7 @@ nsXULPopupManager::HandleShortcutNavigation(nsIDOMKeyEvent* aKeyEvent,
|
||||
bool action;
|
||||
nsMenuFrame* result = aFrame->FindMenuWithShortcut(aKeyEvent, action);
|
||||
if (result) {
|
||||
aFrame->ChangeMenuItem(result, false);
|
||||
aFrame->ChangeMenuItem(result, false, true);
|
||||
if (action) {
|
||||
WidgetGUIEvent* evt = aKeyEvent->GetInternalNSEvent()->AsGUIEvent();
|
||||
nsMenuFrame* menuToOpen = result->Enter(evt);
|
||||
@@ -2068,7 +2091,7 @@ nsXULPopupManager::HandleKeyboardNavigation(uint32_t aKeyCode)
|
||||
nsMenuFrame* nextItem = (theDirection == eNavigationDirection_End) ?
|
||||
GetNextMenuItem(mActiveMenuBar, currentMenu, false) :
|
||||
GetPreviousMenuItem(mActiveMenuBar, currentMenu, false);
|
||||
mActiveMenuBar->ChangeMenuItem(nextItem, true);
|
||||
mActiveMenuBar->ChangeMenuItem(nextItem, true, true);
|
||||
return true;
|
||||
}
|
||||
else if (NS_DIRECTION_IS_BLOCK(theDirection)) {
|
||||
@@ -2104,7 +2127,7 @@ nsXULPopupManager::HandleKeyboardNavigationInPopup(nsMenuChainItem* item,
|
||||
if (aDir == eNavigationDirection_End) {
|
||||
nsMenuFrame* nextItem = GetNextMenuItem(aFrame, nullptr, true);
|
||||
if (nextItem) {
|
||||
aFrame->ChangeMenuItem(nextItem, false);
|
||||
aFrame->ChangeMenuItem(nextItem, false, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2146,7 +2169,7 @@ nsXULPopupManager::HandleKeyboardNavigationInPopup(nsMenuChainItem* item,
|
||||
nextItem = GetPreviousMenuItem(aFrame, nullptr, true);
|
||||
|
||||
if (nextItem) {
|
||||
aFrame->ChangeMenuItem(nextItem, false);
|
||||
aFrame->ChangeMenuItem(nextItem, false, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,6 +240,7 @@ function test_menulist_open(element, scroller)
|
||||
element.appendItem("Scroll Item 1", "scrollitem1");
|
||||
element.appendItem("Scroll Item 2", "scrollitem2");
|
||||
element.focus();
|
||||
element.selectedIndex = 0;
|
||||
|
||||
/*
|
||||
// bug 530504, mousewheel while menulist is open should not scroll menulist
|
||||
@@ -254,13 +255,14 @@ function test_menulist_open(element, scroller)
|
||||
window.removeEventListener("DOMMouseScroll", mouseScrolled, false);
|
||||
*/
|
||||
|
||||
// bug 543065, hovering the mouse over an item should highlight it and not
|
||||
// scroll the parent
|
||||
// bug 543065, hovering the mouse over an item should highlight it, not
|
||||
// scroll the parent, and not change the selected index.
|
||||
var item = element.menupopup.childNodes[1];
|
||||
|
||||
synthesizeMouse(element.menupopup.childNodes[1], 2, 2, { type: "mousemove" });
|
||||
synthesizeMouse(element.menupopup.childNodes[1], 6, 6, { type: "mousemove" });
|
||||
is(element.menuBoxObject.activeChild, item, "activeChild 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);
|
||||
|
||||
element.open = false;
|
||||
|
||||
@@ -19,6 +19,14 @@
|
||||
</menupopup>
|
||||
</menulist>
|
||||
<button id="button2" label="Two"/>
|
||||
<menulist id="list2">
|
||||
<menupopup id="popup" onpopupshown="checkCursorNavigation();" onpopuphidden="done()">
|
||||
<menuitem id="b1" label="One"/>
|
||||
<menuitem id="b2" label="Two" selected="true"/>
|
||||
<menuitem id="b3" label="Three"/>
|
||||
<menuitem id="b4" label="Four"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
<![CDATA[
|
||||
@@ -27,6 +35,10 @@ SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var gShowPopup = false;
|
||||
var gModifiers = 0;
|
||||
var gOpenPhase = false;
|
||||
|
||||
var list = $("list");
|
||||
let expectCommandEvent;
|
||||
|
||||
var iswin = (navigator.platform.indexOf("Win") == 0);
|
||||
|
||||
@@ -34,9 +46,11 @@ function runTests()
|
||||
{
|
||||
var list = $("list");
|
||||
list.focus();
|
||||
|
||||
// on Mac, up and cursor keys open the menu, but on other platforms, the
|
||||
// cursor keys navigate between items without opening the menu
|
||||
if (navigator.platform.indexOf("Mac") == -1) {
|
||||
expectCommandEvent = true;
|
||||
keyCheck(list, "VK_DOWN", 2, "cursor down");
|
||||
keyCheck(list, "VK_DOWN", iswin ? "2b" : 3, "cursor down skip disabled");
|
||||
keyCheck(list, "VK_UP", 2, "cursor up skip disabled");
|
||||
@@ -51,19 +65,35 @@ function runTests()
|
||||
synthesizeKey("VK_UP", { altKey: navigator.platform.indexOf("Mac") == -1 });
|
||||
is(list.selectedItem, $("i1"), "open menulist up selectedItem");
|
||||
|
||||
list.selectedItem = $("i1");
|
||||
|
||||
pressLetter();
|
||||
}
|
||||
|
||||
function pressLetter()
|
||||
{
|
||||
// A command event should be fired only if the menulist is closed, or on Windows,
|
||||
// where items are selected immediately.
|
||||
expectCommandEvent = !gOpenPhase || iswin;
|
||||
|
||||
synthesizeKey("G", { });
|
||||
is(list.selectedItem, $("i1"), "letter pressed not found selectedItem");
|
||||
|
||||
keyCheck(list, "T", 2, "letter pressed");
|
||||
SpecialPowers.setIntPref("ui.menu.incremental_search.timeout", 0); // prevent to timeout
|
||||
keyCheck(list, "T", 2, "letter pressed");
|
||||
SpecialPowers.clearUserPref("ui.menu.incremental_search.timeout");
|
||||
setTimeout(pressedAgain, 1200);
|
||||
|
||||
if (!gOpenPhase) {
|
||||
SpecialPowers.setIntPref("ui.menu.incremental_search.timeout", 0); // prevent to timeout
|
||||
keyCheck(list, "T", 2, "same letter pressed");
|
||||
SpecialPowers.clearUserPref("ui.menu.incremental_search.timeout");
|
||||
}
|
||||
|
||||
setTimeout(pressedAgain, 1200);
|
||||
}
|
||||
|
||||
function pressedAgain()
|
||||
{
|
||||
var list = $("list");
|
||||
|
||||
keyCheck(list, "T", iswin ? "2b" : 3, "letter pressed again");
|
||||
SpecialPowers.setIntPref("ui.menu.incremental_search.timeout", 0); // prevent to timeout
|
||||
keyCheck(list, "W", 2, "second letter pressed");
|
||||
@@ -74,8 +104,32 @@ function pressedAgain()
|
||||
function differentPressed()
|
||||
{
|
||||
var list = $("list");
|
||||
|
||||
keyCheck(list, "O", 1, "different letter pressed");
|
||||
|
||||
if (gOpenPhase) {
|
||||
list.open = false;
|
||||
tabAndScroll();
|
||||
}
|
||||
else {
|
||||
// Run the letter tests again with the popup open
|
||||
info("list open phase");
|
||||
|
||||
list.selectedItem = $("i1");
|
||||
|
||||
gShowPopup = true;
|
||||
list.open = true;
|
||||
gOpenPhase = true;
|
||||
|
||||
list.addEventListener("popupshown", function popupShownListener() {
|
||||
list.removeEventListener("popupshown", popupShownListener, false);
|
||||
pressLetter();
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
function tabAndScroll()
|
||||
{
|
||||
if (navigator.platform.indexOf("Mac") == -1) {
|
||||
$("button1").focus();
|
||||
synthesizeKeyExpectEvent("VK_TAB", { }, list, "focus", "focus to menulist");
|
||||
@@ -84,7 +138,6 @@ function differentPressed()
|
||||
}
|
||||
|
||||
// now make sure that using a key scrolls the menu correctly
|
||||
gShowPopup = true;
|
||||
|
||||
for (let i = 0; i < 65; i++) {
|
||||
list.appendItem("Item" + i, "item" + i);
|
||||
@@ -123,8 +176,8 @@ function differentPressed()
|
||||
function keyCheck(list, key, index, testname)
|
||||
{
|
||||
var item = $("i" + index);
|
||||
synthesizeKeyExpectEvent(key, { }, item, "command", testname);
|
||||
is(list.selectedItem, item, testname + " selectedItem");
|
||||
synthesizeKeyExpectEvent(key, { }, item, expectCommandEvent ? "command" : "!command", testname);
|
||||
is(list.selectedItem, expectCommandEvent ? item : $("i1"), testname + " selectedItem");
|
||||
}
|
||||
|
||||
function checkModifiers(event)
|
||||
@@ -154,13 +207,13 @@ function checkEnterWithModifiers()
|
||||
ok(!list.open, "list closed on enter press");
|
||||
list.removeEventListener("popuphidden", checkEnterWithModifiers, false);
|
||||
|
||||
list.addEventListener("popuphidden", done, false);
|
||||
list.addEventListener("popuphidden", verifyPopupOnClose, false);
|
||||
list.open = true;
|
||||
|
||||
synthesizeKey("VK_RETURN", { shiftKey: true, ctrlKey: true, altKey: true, metaKey: true });
|
||||
}
|
||||
|
||||
function done()
|
||||
function verifyPopupOnClose()
|
||||
{
|
||||
is(gModifiers, 2, "modifiers checked when set");
|
||||
|
||||
@@ -168,6 +221,35 @@ function done()
|
||||
ok(!list.open, "list closed on enter press with modifiers");
|
||||
list.removeEventListener("popuphidden", done, false);
|
||||
|
||||
list = $("list2");
|
||||
list.focus();
|
||||
list.open = true;
|
||||
}
|
||||
|
||||
function checkCursorNavigation()
|
||||
{
|
||||
var list = $("list2");
|
||||
|
||||
var commandEventsCount = 0;
|
||||
list.addEventListener("command", event => {
|
||||
is(event.target, list.selectedItem, "command event fired on selected item");
|
||||
commandEventsCount++;
|
||||
}, false);
|
||||
|
||||
is(list.selectedIndex, 1, "selectedIndex before cursor down");
|
||||
synthesizeKey("VK_DOWN", { });
|
||||
is(list.selectedIndex, iswin ? 2 : 1, "selectedIndex after cursor down");
|
||||
is(commandEventsCount, iswin ? 1 : 0, "selectedIndex after cursor down command event");
|
||||
is(list.menupopup.state, "open", "cursor down popup state");
|
||||
synthesizeKey("VK_PAGE_DOWN", { });
|
||||
is(list.selectedIndex, iswin ? 3 : 1, "selectedIndex after page down");
|
||||
is(commandEventsCount, iswin ? 2 : 0, "selectedIndex after page down command event");
|
||||
is(list.menupopup.state, "open", "page down popup state");
|
||||
list.open = false;
|
||||
}
|
||||
|
||||
function done()
|
||||
{
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ this.EXPORTED_SYMBOLS = [
|
||||
|
||||
this.SelectContentHelper = function (aElement, aGlobal) {
|
||||
this.element = aElement;
|
||||
this.initialSelection = aElement[aElement.selectedIndex] || null;
|
||||
this.global = aGlobal;
|
||||
this.init();
|
||||
this.showDropDown();
|
||||
@@ -60,16 +61,16 @@ this.SelectContentHelper.prototype = {
|
||||
receiveMessage: function(message) {
|
||||
switch (message.name) {
|
||||
case "Forms:SelectDropDownItem":
|
||||
if (this.element.selectedIndex != message.data.value) {
|
||||
this.element.selectedIndex = message.data.value;
|
||||
this.element.selectedIndex = message.data.value;
|
||||
break;
|
||||
|
||||
case "Forms:DismissedDropDown":
|
||||
if (this.initialSelection != this.element.item[this.element.selectedIndex]) {
|
||||
let event = this.element.ownerDocument.createEvent("Events");
|
||||
event.initEvent("change", true, true);
|
||||
this.element.dispatchEvent(event);
|
||||
}
|
||||
|
||||
//intentional fall-through
|
||||
case "Forms:DismissedDropDown":
|
||||
this.uninit();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -37,9 +37,6 @@ this.SelectParentHelper = {
|
||||
},
|
||||
|
||||
handleEvent: function(event) {
|
||||
let popup = event.currentTarget;
|
||||
let menulist = popup.parentNode;
|
||||
|
||||
switch (event.type) {
|
||||
case "command":
|
||||
if (event.target.hasAttribute("value")) {
|
||||
@@ -47,14 +44,14 @@ this.SelectParentHelper = {
|
||||
value: event.target.value
|
||||
});
|
||||
}
|
||||
popup.hidePopup();
|
||||
break;
|
||||
|
||||
case "popuphidden":
|
||||
currentBrowser.messageManager.sendAsyncMessage("Forms:DismissedDropDown", {});
|
||||
currentBrowser = null;
|
||||
let popup = event.target;
|
||||
this._unregisterListeners(popup);
|
||||
menulist.hidden = true;
|
||||
popup.parentNode.hidden = true;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user