diff options
author | Matt A. Tobin <email@mattatobin.com> | 2020-04-14 21:24:51 -0400 |
---|---|---|
committer | Matt A. Tobin <email@mattatobin.com> | 2020-04-14 21:25:54 -0400 |
commit | acb801bdca3c4768346f5a9ea2f1272f3f6434fc (patch) | |
tree | 07b5c3969b8be3992d9442b58cf925869576e34e /dom/html | |
parent | 96b6ea0b94721c6bc1f44f6513f587b1686fec23 (diff) | |
download | uxp-acb801bdca3c4768346f5a9ea2f1272f3f6434fc.tar.gz |
Bug 1305458 - Changing -moz-appearence on hover breaks change event
* Rename nsIDOMEventTarget::PreHandleEvent to nsIDOMEventTarget::GetEventTargetParent
* Add nsIDOMEventTarget::PreHandleEvent
* Add EventTargetChainItem::GetFirstEventTarget
* Call EventTargetChainItem::PreHandleEvent even it sets mCanHandle=false
* Move form control frame focus/blur from nsGenericHTMLFormElement::GetEventTargetParent to PreHandleEvent
* Move fire change event from HTMLTextAreaElement::GetEventTargetParent to PreHandleEvent
* Refine nsXULElement::GetEventTargetParent
* Move dispatch XUL command from nsXULElement::GetEventTargetParent to PreHandleEvent
* Move fire events and set value from HTMLInputElement::GetEventTargetParent to PreHandleEvent
* Add test case
* Let HTMLInputElement delegate event handling to it's parent class
* Refine EventTargetChain flags to reduce overheads
* Refine event target chain creation
* Refine assertion in EventTargetChainItem::Create
Tag mcp-graveyard/UXP#1375
Diffstat (limited to 'dom/html')
28 files changed, 147 insertions, 75 deletions
diff --git a/dom/html/HTMLAnchorElement.cpp b/dom/html/HTMLAnchorElement.cpp index a6cfacc53d..501d6e3d06 100644 --- a/dom/html/HTMLAnchorElement.cpp +++ b/dom/html/HTMLAnchorElement.cpp @@ -252,9 +252,9 @@ HTMLAnchorElement::IsHTMLFocusable(bool aWithMouse, } nsresult -HTMLAnchorElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLAnchorElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { - return PreHandleEventForAnchors(aVisitor); + return GetEventTargetParentForAnchors(aVisitor); } nsresult diff --git a/dom/html/HTMLAnchorElement.h b/dom/html/HTMLAnchorElement.h index 2cb04ad939..027d8d689a 100644 --- a/dom/html/HTMLAnchorElement.h +++ b/dom/html/HTMLAnchorElement.h @@ -58,7 +58,8 @@ public: bool aNullParent = true) override; virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override; - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; virtual nsresult PostHandleEvent( EventChainPostVisitor& aVisitor) override; virtual bool IsLink(nsIURI** aURI) const override; diff --git a/dom/html/HTMLAreaElement.cpp b/dom/html/HTMLAreaElement.cpp index 098081b8b0..213d4831dd 100644 --- a/dom/html/HTMLAreaElement.cpp +++ b/dom/html/HTMLAreaElement.cpp @@ -81,9 +81,9 @@ HTMLAreaElement::SetTarget(const nsAString& aValue) } nsresult -HTMLAreaElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLAreaElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { - return PreHandleEventForAnchors(aVisitor); + return GetEventTargetParentForAnchors(aVisitor); } nsresult diff --git a/dom/html/HTMLAreaElement.h b/dom/html/HTMLAreaElement.h index 650c0fd8fd..c2ed7a9283 100644 --- a/dom/html/HTMLAreaElement.h +++ b/dom/html/HTMLAreaElement.h @@ -44,7 +44,8 @@ public: // nsIDOMHTMLAreaElement NS_DECL_NSIDOMHTMLAREAELEMENT - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; virtual nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override; virtual bool IsLink(nsIURI** aURI) const override; virtual void GetLinkTarget(nsAString& aTarget) override; diff --git a/dom/html/HTMLButtonElement.cpp b/dom/html/HTMLButtonElement.cpp index 435aa9f7fd..aad1c412bc 100644 --- a/dom/html/HTMLButtonElement.cpp +++ b/dom/html/HTMLButtonElement.cpp @@ -207,7 +207,7 @@ HTMLButtonElement::IsDisabledForEvents(EventMessage aMessage) } nsresult -HTMLButtonElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLButtonElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { aVisitor.mCanHandle = false; if (IsDisabledForEvents(aVisitor.mEvent->mMessage)) { @@ -235,7 +235,7 @@ HTMLButtonElement::PreHandleEvent(EventChainPreVisitor& aVisitor) } } - return nsGenericHTMLElement::PreHandleEvent(aVisitor); + return nsGenericHTMLElement::GetEventTargetParent(aVisitor); } nsresult diff --git a/dom/html/HTMLButtonElement.h b/dom/html/HTMLButtonElement.h index ecd9e03d73..a8d206dd69 100644 --- a/dom/html/HTMLButtonElement.h +++ b/dom/html/HTMLButtonElement.h @@ -57,7 +57,8 @@ public: virtual void FieldSetDisabledChanged(bool aNotify) override; // nsIDOMEventTarget - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; virtual nsresult PostHandleEvent( EventChainPostVisitor& aVisitor) override; diff --git a/dom/html/HTMLCanvasElement.cpp b/dom/html/HTMLCanvasElement.cpp index 4b5deab187..803c60e8ac 100644 --- a/dom/html/HTMLCanvasElement.cpp +++ b/dom/html/HTMLCanvasElement.cpp @@ -574,7 +574,7 @@ HTMLCanvasElement::CopyInnerTo(Element* aDest) return rv; } -nsresult HTMLCanvasElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +nsresult HTMLCanvasElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { if (aVisitor.mEvent->mClass == eMouseEventClass) { WidgetMouseEventBase* evt = (WidgetMouseEventBase*)aVisitor.mEvent; @@ -592,7 +592,7 @@ nsresult HTMLCanvasElement::PreHandleEvent(EventChainPreVisitor& aVisitor) aVisitor.mCanHandle = true; } } - return nsGenericHTMLElement::PreHandleEvent(aVisitor); + return nsGenericHTMLElement::GetEventTargetParent(aVisitor); } nsChangeHint diff --git a/dom/html/HTMLCanvasElement.h b/dom/html/HTMLCanvasElement.h index e77db6ff1a..de26c475a3 100644 --- a/dom/html/HTMLCanvasElement.h +++ b/dom/html/HTMLCanvasElement.h @@ -312,7 +312,8 @@ public: virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override; nsresult CopyInnerTo(mozilla::dom::Element* aDest); - virtual nsresult PreHandleEvent(mozilla::EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + mozilla::EventChainPreVisitor& aVisitor) override; /* * Helpers called by various users of Canvas diff --git a/dom/html/HTMLFieldSetElement.cpp b/dom/html/HTMLFieldSetElement.cpp index d72fd1061a..c008b9b6d6 100644 --- a/dom/html/HTMLFieldSetElement.cpp +++ b/dom/html/HTMLFieldSetElement.cpp @@ -70,7 +70,7 @@ HTMLFieldSetElement::IsDisabledForEvents(EventMessage aMessage) // nsIContent nsresult -HTMLFieldSetElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLFieldSetElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { // Do not process any DOM events if the element is disabled. aVisitor.mCanHandle = false; @@ -78,7 +78,7 @@ HTMLFieldSetElement::PreHandleEvent(EventChainPreVisitor& aVisitor) return NS_OK; } - return nsGenericHTMLFormElement::PreHandleEvent(aVisitor); + return nsGenericHTMLFormElement::GetEventTargetParent(aVisitor); } nsresult diff --git a/dom/html/HTMLFieldSetElement.h b/dom/html/HTMLFieldSetElement.h index 96fff4582b..1e9f0214f5 100644 --- a/dom/html/HTMLFieldSetElement.h +++ b/dom/html/HTMLFieldSetElement.h @@ -40,7 +40,8 @@ public: NS_DECL_NSIDOMHTMLFIELDSETELEMENT // nsIContent - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, bool aNotify) override; diff --git a/dom/html/HTMLFormElement.cpp b/dom/html/HTMLFormElement.cpp index 6bea19a2bf..bdc05b053c 100644 --- a/dom/html/HTMLFormElement.cpp +++ b/dom/html/HTMLFormElement.cpp @@ -489,7 +489,7 @@ HTMLFormElement::UnbindFromTree(bool aDeep, bool aNullParent) } nsresult -HTMLFormElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLFormElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { aVisitor.mWantsWillHandleEvent = true; if (aVisitor.mEvent->mOriginalTarget == static_cast<nsIContent*>(this)) { @@ -513,7 +513,7 @@ HTMLFormElement::PreHandleEvent(EventChainPreVisitor& aVisitor) mGeneratingReset = true; } } - return nsGenericHTMLElement::PreHandleEvent(aVisitor); + return nsGenericHTMLElement::GetEventTargetParent(aVisitor); } nsresult diff --git a/dom/html/HTMLFormElement.h b/dom/html/HTMLFormElement.h index b3e836f5f2..e45d4c10d7 100644 --- a/dom/html/HTMLFormElement.h +++ b/dom/html/HTMLFormElement.h @@ -93,7 +93,8 @@ public: nsIAtom* aAttribute, const nsAString& aValue, nsAttrValue& aResult) override; - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; virtual nsresult WillHandleEvent( EventChainPostVisitor& aVisitor) override; virtual nsresult PostHandleEvent( diff --git a/dom/html/HTMLImageElement.cpp b/dom/html/HTMLImageElement.cpp index fab1cdef4b..49cbebc5a4 100644 --- a/dom/html/HTMLImageElement.cpp +++ b/dom/html/HTMLImageElement.cpp @@ -437,7 +437,7 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } nsresult -HTMLImageElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLImageElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { // We handle image element with attribute ismap in its corresponding frame // element. Set mMultipleActionsPrevented here to prevent the click event @@ -446,7 +446,7 @@ HTMLImageElement::PreHandleEvent(EventChainPreVisitor& aVisitor) if (mouseEvent && mouseEvent->IsLeftClickEvent() && IsMap()) { mouseEvent->mFlags.mMultipleActionsPrevented = true; } - return nsGenericHTMLElement::PreHandleEvent(aVisitor); + return nsGenericHTMLElement::GetEventTargetParent(aVisitor); } bool diff --git a/dom/html/HTMLImageElement.h b/dom/html/HTMLImageElement.h index 62323e8016..41730c2e5b 100644 --- a/dom/html/HTMLImageElement.h +++ b/dom/html/HTMLImageElement.h @@ -70,7 +70,8 @@ public: NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override; virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override; - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override; diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp index 0b879bb9b4..d5fca28f6b 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -147,6 +147,8 @@ namespace dom { #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) // whether textfields should be selected once focused: // -1: no, 1: yes, 0: uninitialized @@ -3738,7 +3740,7 @@ HTMLInputElement::IsDisabledForEvents(EventMessage aMessage) } nsresult -HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLInputElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { // Do not process any DOM events if the element is disabled aVisitor.mCanHandle = false; @@ -3755,7 +3757,7 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor) //FIXME Allow submission etc. also when there is no prescontext, Bug 329509. if (!aVisitor.mPresContext) { - return nsGenericHTMLElement::PreHandleEvent(aVisitor); + return nsGenericHTMLFormElementWithState::GetEventTargetParent(aVisitor); } // // Web pages expect the value of a radio button or checkbox to be set @@ -3865,23 +3867,16 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor) // Fire onchange (if necessary), before we do the blur, bug 357684. if (aVisitor.mEvent->mMessage == eBlur) { - // Experimental mobile types rely on the system UI to prevent users to not - // set invalid values but we have to be extra-careful. Especially if the - // option has been enabled on desktop. - if (IsExperimentalMobileType(mType)) { - nsAutoString aValue; - GetValueInternal(aValue); - nsresult rv = - SetValueInternal(aValue, nsTextEditorState::eSetValue_Internal); - NS_ENSURE_SUCCESS(rv, rv); - } - FireChangeEventIfNeeded(); + // We set NS_PRE_HANDLE_BLUR_EVENT here and handle it in PreHandleEvent to + // prevent breaking event target chain creation. + aVisitor.mWantsPreHandleEvent = true; + aVisitor.mItemFlags |= NS_PRE_HANDLE_BLUR_EVENT; } if (mType == NS_FORM_INPUT_RANGE && (aVisitor.mEvent->mMessage == eFocus || aVisitor.mEvent->mMessage == eBlur)) { - // Just as nsGenericHTMLFormElementWithState::PreHandleEvent calls + // Just as nsGenericHTMLFormElementWithState::GetEventTargetParent calls // nsIFormControlFrame::SetFocus, we handle focus here. nsIFrame* frame = GetPrimaryFrame(); if (frame) { @@ -3969,10 +3964,11 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor) } } - nsresult rv = nsGenericHTMLFormElementWithState::PreHandleEvent(aVisitor); + nsresult rv = nsGenericHTMLFormElementWithState::GetEventTargetParent(aVisitor); - // We do this after calling the base class' PreHandleEvent so that - // nsIContent::PreHandleEvent doesn't reset any change we make to mCanHandle. + // We do this after calling the base class' GetEventTargetParent so that + // nsIContent::GetEventTargetParent doesn't reset any change we make to + // mCanHandle. if (mType == NS_FORM_INPUT_NUMBER && aVisitor.mEvent->IsTrusted() && aVisitor.mEvent->mOriginalTarget != this) { @@ -3987,18 +3983,10 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor) } if (textControl && aVisitor.mEvent->mOriginalTarget == textControl) { if (aVisitor.mEvent->mMessage == eEditorInput) { - // Propogate the anon text control's new value to our HTMLInputElement: - nsAutoString value; - numberControlFrame->GetValueOfAnonTextControl(value); - numberControlFrame->HandlingInputEvent(true); - nsWeakFrame weakNumberControlFrame(numberControlFrame); - rv = SetValueInternal(value, - nsTextEditorState::eSetValue_BySetUserInput | - nsTextEditorState::eSetValue_Notify); - NS_ENSURE_SUCCESS(rv, rv); - if (weakNumberControlFrame.IsAlive()) { - numberControlFrame->HandlingInputEvent(false); - } + aVisitor.mWantsPreHandleEvent = true; + // We set NS_PRE_HANDLE_INPUT_EVENT here and handle it in PreHandleEvent + // to prevent breaking event target chain creation. + aVisitor.mItemFlags |= NS_PRE_HANDLE_INPUT_EVENT; } else if (aVisitor.mEvent->mMessage == eFormChange) { // We cancel the DOM 'change' event that is fired for any change to our @@ -4037,6 +4025,50 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor) return rv; } +nsresult +HTMLInputElement::PreHandleEvent(EventChainVisitor& aVisitor) +{ + if (!aVisitor.mPresContext) { + return nsGenericHTMLFormElementWithState::PreHandleEvent(aVisitor); + } + nsresult rv; + if (aVisitor.mItemFlags & NS_PRE_HANDLE_BLUR_EVENT) { + MOZ_ASSERT(aVisitor.mEvent->mMessage == eBlur); + // Experimental mobile types rely on the system UI to prevent users to not + // set invalid values but we have to be extra-careful. Especially if the + // option has been enabled on desktop. + if (IsExperimentalMobileType(mType)) { + nsAutoString aValue; + GetValueInternal(aValue); + nsresult rv = + SetValueInternal(aValue, nsTextEditorState::eSetValue_Internal); + NS_ENSURE_SUCCESS(rv, rv); + } + FireChangeEventIfNeeded(); + } + rv = nsGenericHTMLFormElementWithState::PreHandleEvent(aVisitor); + if (aVisitor.mItemFlags & NS_PRE_HANDLE_INPUT_EVENT) { + nsNumberControlFrame* numberControlFrame = do_QueryFrame(GetPrimaryFrame()); + MOZ_ASSERT(aVisitor.mEvent->mMessage == eEditorInput); + MOZ_ASSERT(numberControlFrame); + MOZ_ASSERT(numberControlFrame->GetAnonTextControl() == + aVisitor.mEvent->mOriginalTarget); + // Propogate the anon text control's new value to our HTMLInputElement: + nsAutoString value; + numberControlFrame->GetValueOfAnonTextControl(value); + numberControlFrame->HandlingInputEvent(true); + nsWeakFrame weakNumberControlFrame(numberControlFrame); + rv = SetValueInternal(value, + nsTextEditorState::eSetValue_BySetUserInput | + nsTextEditorState::eSetValue_Notify); + NS_ENSURE_SUCCESS(rv, rv); + if (weakNumberControlFrame.IsAlive()) { + numberControlFrame->HandlingInputEvent(false); + } + } + return rv; +} + void HTMLInputElement::StartRangeThumbDrag(WidgetGUIEvent* aEvent) { diff --git a/dom/html/HTMLInputElement.h b/dom/html/HTMLInputElement.h index 98a5904437..98c74893e6 100644 --- a/dom/html/HTMLInputElement.h +++ b/dom/html/HTMLInputElement.h @@ -185,7 +185,9 @@ public: NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override; virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override; - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; + virtual nsresult PreHandleEvent(EventChainVisitor& aVisitor) override; virtual nsresult PostHandleEvent( EventChainPostVisitor& aVisitor) override; void PostHandleEventForRangeThumb(EventChainPostVisitor& aVisitor); diff --git a/dom/html/HTMLLinkElement.cpp b/dom/html/HTMLLinkElement.cpp index 8afe767bdb..0a2cdaaf40 100644 --- a/dom/html/HTMLLinkElement.cpp +++ b/dom/html/HTMLLinkElement.cpp @@ -421,9 +421,9 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } nsresult -HTMLLinkElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLLinkElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { - return PreHandleEventForAnchors(aVisitor); + return GetEventTargetParentForAnchors(aVisitor); } nsresult diff --git a/dom/html/HTMLLinkElement.h b/dom/html/HTMLLinkElement.h index 421b149e96..1fa154f41e 100644 --- a/dom/html/HTMLLinkElement.h +++ b/dom/html/HTMLLinkElement.h @@ -46,7 +46,8 @@ public: void UpdateImport(); // nsIDOMEventTarget - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; virtual nsresult PostHandleEvent( EventChainPostVisitor& aVisitor) override; diff --git a/dom/html/HTMLMenuItemElement.cpp b/dom/html/HTMLMenuItemElement.cpp index ca8bb4feb5..6a8ad8174c 100644 --- a/dom/html/HTMLMenuItemElement.cpp +++ b/dom/html/HTMLMenuItemElement.cpp @@ -252,7 +252,7 @@ HTMLMenuItemElement::SetChecked(bool aChecked) } nsresult -HTMLMenuItemElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLMenuItemElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { if (aVisitor.mEvent->mMessage == eMouseClick) { @@ -283,7 +283,7 @@ HTMLMenuItemElement::PreHandleEvent(EventChainPreVisitor& aVisitor) aVisitor.mItemFlags |= mType; } - return nsGenericHTMLElement::PreHandleEvent(aVisitor); + return nsGenericHTMLElement::GetEventTargetParent(aVisitor); } nsresult diff --git a/dom/html/HTMLMenuItemElement.h b/dom/html/HTMLMenuItemElement.h index 3c19b1170e..1da63edd05 100644 --- a/dom/html/HTMLMenuItemElement.h +++ b/dom/html/HTMLMenuItemElement.h @@ -36,7 +36,8 @@ public: // nsIDOMHTMLMenuItemElement NS_DECL_NSIDOMHTMLMENUITEMELEMENT - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; virtual nsresult PostHandleEvent( EventChainPostVisitor& aVisitor) override; diff --git a/dom/html/HTMLOptGroupElement.cpp b/dom/html/HTMLOptGroupElement.cpp index 9e738961d8..0424ccef32 100644 --- a/dom/html/HTMLOptGroupElement.cpp +++ b/dom/html/HTMLOptGroupElement.cpp @@ -48,7 +48,7 @@ NS_IMPL_STRING_ATTR(HTMLOptGroupElement, Label, label) nsresult -HTMLOptGroupElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLOptGroupElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { aVisitor.mCanHandle = false; // Do not process any DOM events if the element is disabled @@ -65,7 +65,7 @@ HTMLOptGroupElement::PreHandleEvent(EventChainPreVisitor& aVisitor) } } - return nsGenericHTMLElement::PreHandleEvent(aVisitor); + return nsGenericHTMLElement::GetEventTargetParent(aVisitor); } Element* diff --git a/dom/html/HTMLOptGroupElement.h b/dom/html/HTMLOptGroupElement.h index e46a6a953f..c669f43b48 100644 --- a/dom/html/HTMLOptGroupElement.h +++ b/dom/html/HTMLOptGroupElement.h @@ -35,7 +35,8 @@ public: virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override; // nsIContent - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; virtual EventStates IntrinsicState() const override; diff --git a/dom/html/HTMLSelectElement.cpp b/dom/html/HTMLSelectElement.cpp index 9ba0a1efe9..272a165781 100644 --- a/dom/html/HTMLSelectElement.cpp +++ b/dom/html/HTMLSelectElement.cpp @@ -1442,14 +1442,14 @@ HTMLSelectElement::IsDisabledForEvents(EventMessage aMessage) } nsresult -HTMLSelectElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLSelectElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { aVisitor.mCanHandle = false; if (IsDisabledForEvents(aVisitor.mEvent->mMessage)) { return NS_OK; } - return nsGenericHTMLFormElementWithState::PreHandleEvent(aVisitor); + return nsGenericHTMLFormElementWithState::GetEventTargetParent(aVisitor); } nsresult diff --git a/dom/html/HTMLSelectElement.h b/dom/html/HTMLSelectElement.h index dc1075cd7d..4cb5f90c9f 100644 --- a/dom/html/HTMLSelectElement.h +++ b/dom/html/HTMLSelectElement.h @@ -278,7 +278,8 @@ public: virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; // nsIContent - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; virtual nsresult PostHandleEvent( EventChainPostVisitor& aVisitor) override; diff --git a/dom/html/HTMLTextAreaElement.cpp b/dom/html/HTMLTextAreaElement.cpp index 42bc02435e..796d8a49e9 100644 --- a/dom/html/HTMLTextAreaElement.cpp +++ b/dom/html/HTMLTextAreaElement.cpp @@ -506,7 +506,7 @@ HTMLTextAreaElement::IsDisabledForEvents(EventMessage aMessage) } nsresult -HTMLTextAreaElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +HTMLTextAreaElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { aVisitor.mCanHandle = false; if (IsDisabledForEvents(aVisitor.mEvent->mMessage)) { @@ -534,11 +534,22 @@ HTMLTextAreaElement::PreHandleEvent(EventChainPreVisitor& aVisitor) aVisitor.mEvent->mFlags.mNoContentDispatch = false; } - // Fire onchange (if necessary), before we do the blur, bug 370521. if (aVisitor.mEvent->mMessage == eBlur) { - FireChangeEventIfNeeded(); + // Set mWantsPreHandleEvent and fire change event in PreHandleEvent to + // prevent it breaks event target chain creation. + aVisitor.mWantsPreHandleEvent = true; } + return nsGenericHTMLFormElementWithState::GetEventTargetParent(aVisitor); +} + +nsresult +HTMLTextAreaElement::PreHandleEvent(EventChainVisitor& aVisitor) +{ + if (aVisitor.mEvent->mMessage == eBlur) { + // Fire onchange (if necessary), before we do the blur, bug 370521. + FireChangeEventIfNeeded(); + } return nsGenericHTMLFormElementWithState::PreHandleEvent(aVisitor); } diff --git a/dom/html/HTMLTextAreaElement.h b/dom/html/HTMLTextAreaElement.h index 0390828182..bfc7d203d8 100644 --- a/dom/html/HTMLTextAreaElement.h +++ b/dom/html/HTMLTextAreaElement.h @@ -125,7 +125,9 @@ public: int32_t aModType) const override; NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override; - virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override; + virtual nsresult GetEventTargetParent( + EventChainPreVisitor& aVisitor) override; + virtual nsresult PreHandleEvent(EventChainVisitor& aVisitor) override; virtual nsresult PostHandleEvent( EventChainPostVisitor& aVisitor) override; diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp index 78e4d5b958..394a77a590 100644 --- a/dom/html/nsGenericHTMLElement.cpp +++ b/dom/html/nsGenericHTMLElement.cpp @@ -607,16 +607,16 @@ nsGenericHTMLElement::CheckHandleEventForAnchorsPreconditions( } nsresult -nsGenericHTMLElement::PreHandleEventForAnchors(EventChainPreVisitor& aVisitor) +nsGenericHTMLElement::GetEventTargetParentForAnchors(EventChainPreVisitor& aVisitor) { - nsresult rv = nsGenericHTMLElementBase::PreHandleEvent(aVisitor); + nsresult rv = nsGenericHTMLElementBase::GetEventTargetParent(aVisitor); NS_ENSURE_SUCCESS(rv, rv); if (!CheckHandleEventForAnchorsPreconditions(aVisitor)) { return NS_OK; } - return PreHandleEventForLinks(aVisitor); + return GetEventTargetParentForLinks(aVisitor); } nsresult @@ -2081,7 +2081,19 @@ nsGenericHTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } nsresult -nsGenericHTMLFormElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +nsGenericHTMLFormElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) +{ + if (aVisitor.mEvent->IsTrusted() && (aVisitor.mEvent->mMessage == eFocus || + aVisitor.mEvent->mMessage == eBlur)) { + // We have to handle focus/blur event to change focus states in + // PreHandleEvent to prevent it breaks event target chain creation. + aVisitor.mWantsPreHandleEvent = true; + } + return nsGenericHTMLElement::GetEventTargetParent(aVisitor); +} + +nsresult +nsGenericHTMLFormElement::PreHandleEvent(EventChainVisitor& aVisitor) { if (aVisitor.mEvent->IsTrusted()) { switch (aVisitor.mEvent->mMessage) { @@ -2105,7 +2117,6 @@ nsGenericHTMLFormElement::PreHandleEvent(EventChainPreVisitor& aVisitor) break; } } - return nsGenericHTMLElement::PreHandleEvent(aVisitor); } diff --git a/dom/html/nsGenericHTMLElement.h b/dom/html/nsGenericHTMLElement.h index 2b8b608b9d..ab4391aa1e 100644 --- a/dom/html/nsGenericHTMLElement.h +++ b/dom/html/nsGenericHTMLElement.h @@ -498,7 +498,8 @@ public: */ bool CheckHandleEventForAnchorsPreconditions( mozilla::EventChainVisitor& aVisitor); - nsresult PreHandleEventForAnchors(mozilla::EventChainPreVisitor& aVisitor); + nsresult GetEventTargetParentForAnchors( + mozilla::EventChainPreVisitor& aVisitor); nsresult PostHandleEventForAnchors(mozilla::EventChainPostVisitor& aVisitor); bool IsHTMLLink(nsIURI** aURI) const; @@ -1219,8 +1220,10 @@ public: virtual IMEState GetDesiredIMEState() override; virtual mozilla::EventStates IntrinsicState() const override; - virtual nsresult PreHandleEvent( + virtual nsresult GetEventTargetParent( mozilla::EventChainPreVisitor& aVisitor) override; + virtual nsresult PreHandleEvent( + mozilla::EventChainVisitor& aVisitor) override; /** * This callback is called by a fieldest on all its elements whenever its @@ -1305,7 +1308,7 @@ protected: static bool FormIdUpdated(Element* aOldElement, Element* aNewElement, void* aData); - // Returns true if the event should not be handled from PreHandleEvent + // Returns true if the event should not be handled from GetEventTargetParent bool IsElementDisabledForEvents(mozilla::EventMessage aMessage, nsIFrame* aFrame); |