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 | 5352b69a9286223272c0ed072900b4c78ba2ed7c (patch) | |
tree | 07b5c3969b8be3992d9442b58cf925869576e34e /dom/xul | |
parent | 6f6d1f6ff788b6fac2a137ecbd41762f9976f42d (diff) | |
download | UXP-5352b69a9286223272c0ed072900b4c78ba2ed7c.tar UXP-5352b69a9286223272c0ed072900b4c78ba2ed7c.tar.gz UXP-5352b69a9286223272c0ed072900b4c78ba2ed7c.tar.lz UXP-5352b69a9286223272c0ed072900b4c78ba2ed7c.tar.xz UXP-5352b69a9286223272c0ed072900b4c78ba2ed7c.zip |
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 #1375
Diffstat (limited to 'dom/xul')
-rw-r--r-- | dom/xul/nsXULElement.cpp | 124 | ||||
-rw-r--r-- | dom/xul/nsXULElement.h | 10 |
2 files changed, 84 insertions, 50 deletions
diff --git a/dom/xul/nsXULElement.cpp b/dom/xul/nsXULElement.cpp index a854f53ec..bc9215086 100644 --- a/dom/xul/nsXULElement.cpp +++ b/dom/xul/nsXULElement.cpp @@ -126,6 +126,8 @@ uint32_t nsXULPrototypeAttribute::gNumCacheSets; uint32_t nsXULPrototypeAttribute::gNumCacheFills; #endif +#define NS_DISPATCH_XUL_COMMAND (1 << 0) + class nsXULElementTearoff final : public nsIFrameLoaderOwner { ~nsXULElementTearoff() {} @@ -1236,17 +1238,65 @@ nsXULElement::List(FILE* out, int32_t aIndent) const } #endif +bool +nsXULElement::IsEventStoppedFromAnonymousScrollbar(EventMessage aMessage) +{ + return (IsRootOfNativeAnonymousSubtree() && + IsAnyOfXULElements(nsGkAtoms::scrollbar, nsGkAtoms::scrollcorner) && + (aMessage == eMouseClick || aMessage == eMouseDoubleClick || + aMessage == eXULCommand || aMessage == eContextMenu || + aMessage == eDragStart)); +} + nsresult -nsXULElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +nsXULElement::DispatchXULCommand(const EventChainVisitor& aVisitor, + nsAutoString& aCommand) +{ + // XXX sXBL/XBL2 issue! Owner or current document? + nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(GetUncomposedDoc())); + NS_ENSURE_STATE(domDoc); + nsCOMPtr<nsIDOMElement> commandElt; + domDoc->GetElementById(aCommand, getter_AddRefs(commandElt)); + nsCOMPtr<nsIContent> commandContent(do_QueryInterface(commandElt)); + if (commandContent) { + // Create a new command event to dispatch to the element + // pointed to by the command attribute. The new event's + // sourceEvent will be the original command event that we're + // handling. + nsCOMPtr<nsIDOMEvent> domEvent = aVisitor.mDOMEvent; + while (domEvent) { + Event* event = domEvent->InternalDOMEvent(); + NS_ENSURE_STATE(!SameCOMIdentity(event->GetOriginalTarget(), + commandContent)); + nsCOMPtr<nsIDOMXULCommandEvent> commandEvent = + do_QueryInterface(domEvent); + if (commandEvent) { + commandEvent->GetSourceEvent(getter_AddRefs(domEvent)); + } else { + domEvent = nullptr; + } + } + WidgetInputEvent* orig = aVisitor.mEvent->AsInputEvent(); + nsContentUtils::DispatchXULCommand( + commandContent, + orig->IsTrusted(), + aVisitor.mDOMEvent, + nullptr, + orig->IsControl(), + orig->IsAlt(), + orig->IsShift(), + orig->IsMeta()); + } else { + NS_WARNING("A XUL element is attached to a command that doesn't exist!\n"); + } + return NS_OK; +} + +nsresult +nsXULElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) { aVisitor.mForceContentDispatch = true; //FIXME! Bug 329119 - if (IsRootOfNativeAnonymousSubtree() && - (IsAnyOfXULElements(nsGkAtoms::scrollbar, nsGkAtoms::scrollcorner)) && - (aVisitor.mEvent->mMessage == eMouseClick || - aVisitor.mEvent->mMessage == eMouseDoubleClick || - aVisitor.mEvent->mMessage == eXULCommand || - aVisitor.mEvent->mMessage == eContextMenu || - aVisitor.mEvent->mMessage == eDragStart)) { + if (IsEventStoppedFromAnonymousScrollbar(aVisitor.mEvent->mMessage)) { // Don't propagate these events from native anonymous scrollbar. aVisitor.mCanHandle = true; aVisitor.mParentTarget = nullptr; @@ -1263,55 +1313,33 @@ nsXULElement::PreHandleEvent(EventChainPreVisitor& aVisitor) // See if we have a command elt. If so, we execute on the command // instead of on our content element. nsAutoString command; - if (xulEvent && GetAttr(kNameSpaceID_None, nsGkAtoms::command, command) && + if (xulEvent && + GetAttr(kNameSpaceID_None, nsGkAtoms::command, command) && !command.IsEmpty()) { // Stop building the event target chain for the original event. // We don't want it to propagate to any DOM nodes. aVisitor.mCanHandle = false; aVisitor.mAutomaticChromeDispatch = false; - - // XXX sXBL/XBL2 issue! Owner or current document? - nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(GetUncomposedDoc())); - NS_ENSURE_STATE(domDoc); - nsCOMPtr<nsIDOMElement> commandElt; - domDoc->GetElementById(command, getter_AddRefs(commandElt)); - nsCOMPtr<nsIContent> commandContent(do_QueryInterface(commandElt)); - if (commandContent) { - // Create a new command event to dispatch to the element - // pointed to by the command attribute. The new event's - // sourceEvent will be the original command event that we're - // handling. - nsCOMPtr<nsIDOMEvent> domEvent = aVisitor.mDOMEvent; - while (domEvent) { - Event* event = domEvent->InternalDOMEvent(); - NS_ENSURE_STATE(!SameCOMIdentity(event->GetOriginalTarget(), - commandContent)); - nsCOMPtr<nsIDOMXULCommandEvent> commandEvent = - do_QueryInterface(domEvent); - if (commandEvent) { - commandEvent->GetSourceEvent(getter_AddRefs(domEvent)); - } else { - domEvent = nullptr; - } - } - - WidgetInputEvent* orig = aVisitor.mEvent->AsInputEvent(); - nsContentUtils::DispatchXULCommand( - commandContent, - aVisitor.mEvent->IsTrusted(), - aVisitor.mDOMEvent, - nullptr, - orig->IsControl(), - orig->IsAlt(), - orig->IsShift(), - orig->IsMeta()); - } else { - NS_WARNING("A XUL element is attached to a command that doesn't exist!\n"); - } + // Dispatch XUL command in PreHandleEvent to prevent it breaks event + // target chain creation + aVisitor.mWantsPreHandleEvent = true; + aVisitor.mItemFlags |= NS_DISPATCH_XUL_COMMAND; return NS_OK; } } + return nsStyledElement::GetEventTargetParent(aVisitor); +} + +nsresult +nsXULElement::PreHandleEvent(EventChainVisitor& aVisitor) +{ + if (aVisitor.mItemFlags & NS_DISPATCH_XUL_COMMAND) { + nsAutoString command; + GetAttr(kNameSpaceID_None, nsGkAtoms::command, command); + MOZ_ASSERT(!command.IsEmpty()); + return DispatchXULCommand(aVisitor, command); + } return nsStyledElement::PreHandleEvent(aVisitor); } diff --git a/dom/xul/nsXULElement.h b/dom/xul/nsXULElement.h index 80424412f..109f6c2e7 100644 --- a/dom/xul/nsXULElement.h +++ b/dom/xul/nsXULElement.h @@ -355,9 +355,10 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULElement, nsStyledElement) // nsINode - virtual nsresult PreHandleEvent( + virtual nsresult GetEventTargetParent( mozilla::EventChainPreVisitor& aVisitor) override; - + virtual nsresult PreHandleEvent( + mozilla::EventChainVisitor& aVisitor) override; // nsIContent virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, @@ -689,6 +690,11 @@ protected: virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override; void MaybeUpdatePrivateLifetime(); + + bool IsEventStoppedFromAnonymousScrollbar(mozilla::EventMessage aMessage); + + nsresult DispatchXULCommand(const mozilla::EventChainVisitor& aVisitor, + nsAutoString& aCommand); }; #endif // nsXULElement_h__ |