summaryrefslogtreecommitdiffstats
path: root/dom/xul/nsXULElement.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/xul/nsXULElement.cpp')
-rw-r--r--dom/xul/nsXULElement.cpp124
1 files changed, 76 insertions, 48 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);
}