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.cpp150
1 files changed, 92 insertions, 58 deletions
diff --git a/dom/xul/nsXULElement.cpp b/dom/xul/nsXULElement.cpp
index a854f53ec..2ae03e0b1 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() {}
@@ -202,7 +204,7 @@ nsXULElement::Create(nsXULPrototypeElement* aPrototype, mozilla::dom::NodeInfo *
element->SetHasID();
}
if (aPrototype->mHasClassAttribute) {
- element->SetFlags(NODE_MAY_HAVE_CLASS);
+ element->SetMayHaveClass();
}
if (aPrototype->mHasStyleAttribute) {
element->SetMayHaveStyle();
@@ -358,12 +360,15 @@ nsXULElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
attrValue.SetTo(*originalValue);
}
+ bool oldValueSet;
if (originalName->IsAtom()) {
rv = element->mAttrsAndChildren.SetAndSwapAttr(originalName->Atom(),
- attrValue);
+ attrValue,
+ &oldValueSet);
} else {
rv = element->mAttrsAndChildren.SetAndSwapAttr(originalName->NodeInfo(),
- attrValue);
+ attrValue,
+ &oldValueSet);
}
NS_ENSURE_SUCCESS(rv, rv);
element->AddListenerFor(*originalName, true);
@@ -372,7 +377,7 @@ nsXULElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
element->SetHasID();
}
if (originalName->Equals(nsGkAtoms::_class)) {
- element->SetFlags(NODE_MAY_HAVE_CLASS);
+ element->SetMayHaveClass();
}
if (originalName->Equals(nsGkAtoms::style)) {
element->SetMayHaveStyle();
@@ -1005,7 +1010,7 @@ nsXULElement::UnregisterAccessKey(const nsAString& aOldValue)
nsresult
nsXULElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- nsAttrValueOrString* aValue, bool aNotify)
+ const nsAttrValueOrString* aValue, bool aNotify)
{
if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::accesskey &&
IsInUncomposedDoc()) {
@@ -1051,7 +1056,8 @@ nsXULElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsresult
nsXULElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValue* aValue, bool aNotify)
+ const nsAttrValue* aValue,
+ const nsAttrValue* aOldValue, bool aNotify)
{
if (aNamespaceID == kNameSpaceID_None) {
if (aValue) {
@@ -1172,7 +1178,7 @@ nsXULElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
}
return nsStyledElement::AfterSetAttr(aNamespaceID, aName,
- aValue, aNotify);
+ aValue, aOldValue, aNotify);
}
bool
@@ -1236,20 +1242,68 @@ 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;
+ aVisitor.SetParentTarget(nullptr, false);
return NS_OK;
}
if (aVisitor.mEvent->mMessage == eXULCommand &&
@@ -1263,55 +1317,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);
}
@@ -1880,12 +1912,14 @@ nsXULElement::MakeHeavyweight(nsXULPrototypeElement* aPrototype)
attrValue.SetTo(protoattr->mValue);
}
+ bool oldValueSet;
// XXX we might wanna have a SetAndTakeAttr that takes an nsAttrName
if (protoattr->mName.IsAtom()) {
- rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.Atom(), attrValue);
+ rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.Atom(),
+ attrValue, &oldValueSet);
} else {
rv = mAttrsAndChildren.SetAndSwapAttr(protoattr->mName.NodeInfo(),
- attrValue);
+ attrValue, &oldValueSet);
}
NS_ENSURE_SUCCESS(rv, rv);
}