summaryrefslogtreecommitdiffstats
path: root/dom/xul
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2020-04-14 21:24:51 -0400
committerMatt A. Tobin <email@mattatobin.com>2020-04-14 21:25:54 -0400
commit5352b69a9286223272c0ed072900b4c78ba2ed7c (patch)
tree07b5c3969b8be3992d9442b58cf925869576e34e /dom/xul
parent6f6d1f6ff788b6fac2a137ecbd41762f9976f42d (diff)
downloadUXP-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.cpp124
-rw-r--r--dom/xul/nsXULElement.h10
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__