Bug 1430892: Prevent accidental selection of an item in a dropdown menu and closing the menu on macOS. r=mstange

Differential Revision: https://phabricator.services.mozilla.com/D161310
This commit is contained in:
Stephen A Pohl 2022-12-20 16:55:44 +00:00
parent 8cf450c91a
commit d704105be4
2 changed files with 20 additions and 14 deletions

View file

@ -54,10 +54,10 @@ using dom::Element;
NS_DECLARE_FRAME_PROPERTY_FRAMELIST(PopupListProperty)
// This global flag indicates that a menu just opened or closed and is used
// to ignore the mousemove and mouseup events that would fire on the menu after
// the mousedown occurred.
static int32_t gMenuJustOpenedOrClosed = false;
// This global flag is used to record the timestamp when a menu was opened or
// closed and is used to ignore the mousemove and mouseup events that would fire
// on the menu after the mousedown occurred.
static TimeStamp gMenuJustOpenedOrClosedTime = TimeStamp();
const int32_t kBlinkDelay = 67; // milliseconds
@ -344,9 +344,9 @@ nsresult nsMenuFrame::HandleEvent(nsPresContext* aPresContext,
// If a menu just opened, ignore the mouseup event that might occur after a
// the mousedown event that opened it. However, if a different mousedown
// event occurs, just clear this flag.
if (gMenuJustOpenedOrClosed) {
if (!gMenuJustOpenedOrClosedTime.IsNull()) {
if (aEvent->mMessage == eMouseDown) {
gMenuJustOpenedOrClosed = false;
gMenuJustOpenedOrClosedTime = TimeStamp();
} else if (aEvent->mMessage == eMouseUp) {
return NS_OK;
}
@ -444,8 +444,12 @@ nsresult nsMenuFrame::HandleEvent(nsPresContext* aPresContext,
}
} else if (aEvent->mMessage == eMouseMove &&
(onmenu || (menuParent && menuParent->IsMenuBar()))) {
if (gMenuJustOpenedOrClosed) {
gMenuJustOpenedOrClosed = false;
// Use a tolerance to address situations where a user might perform a
// "wiggly" click that is accompanied by near-simultaneous mousemove events.
TimeDuration tolerance = TimeDuration::FromMilliseconds(200);
if (!gMenuJustOpenedOrClosedTime.IsNull() &&
gMenuJustOpenedOrClosedTime + tolerance < TimeStamp::Now()) {
gMenuJustOpenedOrClosedTime = TimeStamp();
return NS_OK;
}
@ -495,7 +499,7 @@ void nsMenuFrame::ToggleMenuState() {
}
void nsMenuFrame::PopupOpened() {
gMenuJustOpenedOrClosed = true;
gMenuJustOpenedOrClosedTime = TimeStamp::Now();
AutoWeakFrame weakFrame(this);
mContent->AsElement()->SetAttr(kNameSpaceID_None, nsGkAtoms::open, u"true"_ns,
@ -638,7 +642,7 @@ void nsMenuFrame::OpenMenu(bool aSelectFirstItem) {
}
void nsMenuFrame::CloseMenu(bool aDeselectMenu) {
gMenuJustOpenedOrClosed = true;
gMenuJustOpenedOrClosedTime = TimeStamp::Now();
// Close the menu asynchronously
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();

View file

@ -5,8 +5,8 @@
<window title="Menu with Mouse Capture"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<menulist id="menulist">
<menupopup onpopupshown="shown(this)" onpopuphidden="done();">
@ -32,8 +32,10 @@ function startTest() {
function shown(popup)
{
popup.setCaptureAlways();
synthesizeMouseAtCenter(document.getElementById("menuitem"), { type: "mousemove" });
synthesizeMouseAtCenter(document.getElementById("menuitem"), { type: "mouseup" });
setTimeout(function() {
synthesizeMouseAtCenter(document.getElementById("menuitem"), { type: "mousemove" });
synthesizeMouseAtCenter(document.getElementById("menuitem"), { type: "mouseup" });
}, 200);
}
function done()