diff --git a/dom/html/HTMLButtonElement.cpp b/dom/html/HTMLButtonElement.cpp
index e493d1891d..e3fdbb4d32 100644
--- a/dom/html/HTMLButtonElement.cpp
+++ b/dom/html/HTMLButtonElement.cpp
@@ -221,11 +221,14 @@ HTMLButtonElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
bool outerActivateEvent =
((mouseEvent && mouseEvent->IsLeftClickEvent()) ||
(aVisitor.mEvent->mMessage == eLegacyDOMActivate &&
- !mInInternalActivate));
+ !mInInternalActivate &&
+ aVisitor.mEvent->mOriginalTarget == this));
if (outerActivateEvent) {
aVisitor.mItemFlags |= NS_OUTER_ACTIVATE_EVENT;
- if (mType == NS_FORM_BUTTON_SUBMIT && mForm) {
+ if (mType == NS_FORM_BUTTON_SUBMIT && mForm &&
+ !aVisitor.mEvent->mFlags.mMultiplePreActionsPrevented) {
+ aVisitor.mEvent->mFlags.mMultiplePreActionsPrevented = true;
aVisitor.mItemFlags |= NS_IN_SUBMIT_CLICK;
// tell the form that we are about to enter a click handler.
// that means that if there are scripted submissions, the
diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp
index 557e673e15..2f4ee84a49 100644
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -143,11 +143,14 @@ namespace dom {
#define NS_ORIGINAL_CHECKED_VALUE (1 << 10)
#define NS_NO_CONTENT_DISPATCH (1 << 11)
#define NS_ORIGINAL_INDETERMINATE_VALUE (1 << 12)
-#define NS_CONTROL_TYPE(bits) ((bits) & ~( \
- NS_OUTER_ACTIVATE_EVENT | NS_ORIGINAL_CHECKED_VALUE | NS_NO_CONTENT_DISPATCH | \
- NS_ORIGINAL_INDETERMINATE_VALUE))
#define NS_PRE_HANDLE_BLUR_EVENT (1 << 13)
#define NS_PRE_HANDLE_INPUT_EVENT (1 << 14)
+#define NS_IN_SUBMIT_CLICK (1 << 15)
+#define NS_CONTROL_TYPE(bits) \
+ ((bits) & ~(NS_OUTER_ACTIVATE_EVENT | NS_ORIGINAL_CHECKED_VALUE | \
+ NS_NO_CONTENT_DISPATCH | NS_ORIGINAL_INDETERMINATE_VALUE | \
+ NS_PRE_HANDLE_BLUR_EVENT | NS_PRE_HANDLE_INPUT_EVENT | \
+ NS_IN_SUBMIT_CLICK))
// whether textfields should be selected once focused:
// -1: no, 1: yes, 0: uninitialized
@@ -3800,7 +3803,10 @@ HTMLInputElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
case NS_FORM_INPUT_SUBMIT:
case NS_FORM_INPUT_IMAGE:
- if (mForm) {
+ if (mForm && !aVisitor.mEvent->mFlags.mMultiplePreActionsPrevented) {
+ // Make sure other submit elements don't try to trigger submission.
+ aVisitor.mEvent->mFlags.mMultiplePreActionsPrevented = true;
+ aVisitor.mItemFlags |= NS_IN_SUBMIT_CLICK;
// tell the form that we are about to enter a click handler.
// that means that if there are scripted submissions, the
// latest one will be deferred until after the exit point of the handler.
@@ -4394,17 +4400,15 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
}
}
- if (outerActivateEvent) {
+ if ((aVisitor.mItemFlags & NS_IN_SUBMIT_CLICK) && mForm) {
switch(oldType) {
case NS_FORM_INPUT_SUBMIT:
case NS_FORM_INPUT_IMAGE:
- if (mForm) {
- // tell the form that we are about to exit a click handler
- // so the form knows not to defer subsequent submissions
- // the pending ones that were created during the handler
- // will be flushed or forgoten.
- mForm->OnSubmitClickEnd();
- }
+ // tell the form that we are about to exit a click handler
+ // so the form knows not to defer subsequent submissions
+ // the pending ones that were created during the handler
+ // will be flushed or forgoten.
+ mForm->OnSubmitClickEnd();
break;
default:
break;
@@ -4770,7 +4774,8 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
if (outerActivateEvent) {
if (mForm && (oldType == NS_FORM_INPUT_SUBMIT ||
oldType == NS_FORM_INPUT_IMAGE)) {
- if (mType != NS_FORM_INPUT_SUBMIT && mType != NS_FORM_INPUT_IMAGE) {
+ if (mType != NS_FORM_INPUT_SUBMIT && mType != NS_FORM_INPUT_IMAGE &&
+ aVisitor.mItemFlags & NS_IN_SUBMIT_CLICK) {
// If the type has changed to a non-submit type, then we want to
// flush the stored submission if there is one (as if the submit()
// was allowed to succeed)
@@ -4809,7 +4814,7 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
break;
} //switch
} //click or outer activate event
- } else if (outerActivateEvent &&
+ } else if ((aVisitor.mItemFlags & NS_IN_SUBMIT_CLICK) &&
(oldType == NS_FORM_INPUT_SUBMIT ||
oldType == NS_FORM_INPUT_IMAGE) &&
mForm) {
diff --git a/layout/forms/nsHTMLButtonControlFrame.cpp b/layout/forms/nsHTMLButtonControlFrame.cpp
index 1ec0ec6c94..d1fbfbabd7 100644
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -118,8 +118,8 @@ nsHTMLButtonControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsDisplayListCollection set(aBuilder);
- // Do not allow the child subtree to receive events.
- if (!isForEventDelivery) {
+ // HTMLInputElement buttons are opaque to hit tests, HTMLButtonElement buttons are not.
+ if (!(isForEventDelivery && this->IsInput())) {
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
if (ShouldClipPaintingToBorderBox()) {
diff --git a/widget/BasicEvents.h b/widget/BasicEvents.h
index 0ce0f587dd..9631dfd257 100644
--- a/widget/BasicEvents.h
+++ b/widget/BasicEvents.h
@@ -80,6 +80,8 @@ public:
// the first