mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-29 11:57:32 +09:00
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
This commit is contained in:
parent
20b2c26451
commit
cb2b45e472
70 changed files with 547 additions and 258 deletions
|
|
@ -69,7 +69,7 @@ ArchiveRequest::~ArchiveRequest()
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
ArchiveRequest::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
ArchiveRequest::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
aVisitor.mCanHandle = true;
|
aVisitor.mCanHandle = true;
|
||||||
aVisitor.mParentTarget = nullptr;
|
aVisitor.mParentTarget = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,8 @@ public:
|
||||||
ArchiveReader* aReader);
|
ArchiveReader* aReader);
|
||||||
|
|
||||||
// nsIDOMEventTarget
|
// nsIDOMEventTarget
|
||||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
virtual nsresult GetEventTargetParent(
|
||||||
|
EventChainPreVisitor& aVisitor) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// This is called by the DOMArchiveRequestEvent
|
// This is called by the DOMArchiveRequestEvent
|
||||||
|
|
|
||||||
|
|
@ -344,7 +344,7 @@ Attr::RemoveChildAt(uint32_t aIndex, bool aNotify)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
Attr::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
Attr::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
aVisitor.mCanHandle = true;
|
aVisitor.mCanHandle = true;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ public:
|
||||||
// nsIDOMAttr interface
|
// nsIDOMAttr interface
|
||||||
NS_DECL_NSIDOMATTR
|
NS_DECL_NSIDOMATTR
|
||||||
|
|
||||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
virtual nsresult GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
|
||||||
|
|
||||||
// nsIAttribute interface
|
// nsIAttribute interface
|
||||||
void SetMap(nsDOMAttributeMap *aMap) override;
|
void SetMap(nsDOMAttributeMap *aMap) override;
|
||||||
|
|
|
||||||
|
|
@ -3129,7 +3129,7 @@ Element::CheckHandleEventForLinksPrecondition(EventChainVisitor& aVisitor,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
Element::PreHandleEventForLinks(EventChainPreVisitor& aVisitor)
|
Element::GetEventTargetParentForLinks(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
// Optimisation: return early if this event doesn't interest us.
|
// Optimisation: return early if this event doesn't interest us.
|
||||||
// IMPORTANT: this switch and the switch below it must be kept in sync!
|
// IMPORTANT: this switch and the switch below it must be kept in sync!
|
||||||
|
|
@ -3151,8 +3151,9 @@ Element::PreHandleEventForLinks(EventChainPreVisitor& aVisitor)
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
// We do the status bar updates in PreHandleEvent so that the status bar gets
|
// We do the status bar updates in GetEventTargetParent so that the status bar
|
||||||
// updated even if the event is consumed before we have a chance to set it.
|
// gets updated even if the event is consumed before we have a chance to set
|
||||||
|
// it.
|
||||||
switch (aVisitor.mEvent->mMessage) {
|
switch (aVisitor.mEvent->mMessage) {
|
||||||
// Set the status bar similarly for mouseover and focus
|
// Set the status bar similarly for mouseover and focus
|
||||||
case eMouseOver:
|
case eMouseOver:
|
||||||
|
|
|
||||||
|
|
@ -1400,7 +1400,7 @@ protected:
|
||||||
/**
|
/**
|
||||||
* Handle status bar updates before they can be cancelled.
|
* Handle status bar updates before they can be cancelled.
|
||||||
*/
|
*/
|
||||||
nsresult PreHandleEventForLinks(EventChainPreVisitor& aVisitor);
|
nsresult GetEventTargetParentForLinks(EventChainPreVisitor& aVisitor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle default actions for link event if the event isn't consumed yet.
|
* Handle default actions for link event if the event isn't consumed yet.
|
||||||
|
|
|
||||||
|
|
@ -718,7 +718,7 @@ FindChromeAccessOnlySubtreeOwner(nsIContent* aContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsIContent::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
//FIXME! Document how this event retargeting works, Bug 329124.
|
//FIXME! Document how this event retargeting works, Bug 329124.
|
||||||
aVisitor.mCanHandle = true;
|
aVisitor.mCanHandle = true;
|
||||||
|
|
|
||||||
|
|
@ -7712,7 +7712,7 @@ nsDocument::GetExistingListenerManager() const
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsDocument::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
nsDocument::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
aVisitor.mCanHandle = true;
|
aVisitor.mCanHandle = true;
|
||||||
// FIXME! This is a hack to make middle mouse paste working also in Editor.
|
// FIXME! This is a hack to make middle mouse paste working also in Editor.
|
||||||
|
|
|
||||||
|
|
@ -810,7 +810,7 @@ public:
|
||||||
NS_DECL_NSIDOMDOCUMENTXBL
|
NS_DECL_NSIDOMDOCUMENTXBL
|
||||||
|
|
||||||
// nsIDOMEventTarget
|
// nsIDOMEventTarget
|
||||||
virtual nsresult PreHandleEvent(
|
virtual nsresult GetEventTargetParent(
|
||||||
mozilla::EventChainPreVisitor& aVisitor) override;
|
mozilla::EventChainPreVisitor& aVisitor) override;
|
||||||
virtual mozilla::EventListenerManager*
|
virtual mozilla::EventListenerManager*
|
||||||
GetOrCreateListenerManager() override;
|
GetOrCreateListenerManager() override;
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ public:
|
||||||
virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
|
virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
|
||||||
virtual EventStates IntrinsicState() const override;
|
virtual EventStates IntrinsicState() const override;
|
||||||
|
|
||||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override
|
virtual nsresult GetEventTargetParent(EventChainPreVisitor& aVisitor) override
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(IsInNativeAnonymousSubtree());
|
MOZ_ASSERT(IsInNativeAnonymousSubtree());
|
||||||
if (aVisitor.mEvent->mMessage == eLoad ||
|
if (aVisitor.mEvent->mMessage == eLoad ||
|
||||||
|
|
@ -54,7 +54,7 @@ public:
|
||||||
// Don't propagate the events to the parent.
|
// Don't propagate the events to the parent.
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
return nsXMLElement::PreHandleEvent(aVisitor);
|
return nsXMLElement::GetEventTargetParent(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -3577,9 +3577,10 @@ nsGlobalWindow::WillHandleEvent(EventChainPostVisitor& aVisitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsGlobalWindow::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
nsGlobalWindow::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
NS_PRECONDITION(IsInnerWindow(), "PreHandleEvent is used on outer window!?");
|
NS_PRECONDITION(IsInnerWindow(),
|
||||||
|
"GetEventTargetParent is used on outer window!?");
|
||||||
EventMessage msg = aVisitor.mEvent->mMessage;
|
EventMessage msg = aVisitor.mEvent->mMessage;
|
||||||
|
|
||||||
aVisitor.mCanHandle = true;
|
aVisitor.mCanHandle = true;
|
||||||
|
|
@ -3812,7 +3813,7 @@ nsGlobalWindow::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
||||||
} else if (aVisitor.mEvent->mMessage == eLoad &&
|
} else if (aVisitor.mEvent->mMessage == eLoad &&
|
||||||
aVisitor.mEvent->IsTrusted()) {
|
aVisitor.mEvent->IsTrusted()) {
|
||||||
// This is page load event since load events don't propagate to |window|.
|
// This is page load event since load events don't propagate to |window|.
|
||||||
// @see nsDocument::PreHandleEvent.
|
// @see nsDocument::GetEventTargetParent.
|
||||||
mIsDocumentLoaded = true;
|
mIsDocumentLoaded = true;
|
||||||
|
|
||||||
nsCOMPtr<Element> element = GetOuterWindow()->GetFrameElementInternal();
|
nsCOMPtr<Element> element = GetOuterWindow()->GetFrameElementInternal();
|
||||||
|
|
|
||||||
|
|
@ -947,7 +947,7 @@ public:
|
||||||
// Overloaded from nsINode
|
// Overloaded from nsINode
|
||||||
virtual already_AddRefed<nsIURI> GetBaseURI(bool aTryUseXHRDocBaseURI = false) const override;
|
virtual already_AddRefed<nsIURI> GetBaseURI(bool aTryUseXHRDocBaseURI = false) const override;
|
||||||
|
|
||||||
virtual nsresult PreHandleEvent(
|
virtual nsresult GetEventTargetParent(
|
||||||
mozilla::EventChainPreVisitor& aVisitor) override;
|
mozilla::EventChainPreVisitor& aVisitor) override;
|
||||||
|
|
||||||
virtual bool IsPurple() = 0;
|
virtual bool IsPurple() = 0;
|
||||||
|
|
|
||||||
|
|
@ -1243,7 +1243,7 @@ nsINode::RemoveEventListener(const nsAString& aType,
|
||||||
NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsINode)
|
NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsINode)
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsINode::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
nsINode::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
// This is only here so that we can use the NS_DECL_NSIDOMTARGET macro
|
// This is only here so that we can use the NS_DECL_NSIDOMTARGET macro
|
||||||
NS_ABORT();
|
NS_ABORT();
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,
|
||||||
mozilla::HoldJSObjects(this);
|
mozilla::HoldJSObjects(this);
|
||||||
|
|
||||||
// If owner corresponds to an <iframe mozbrowser> or <iframe mozapp>, we'll
|
// If owner corresponds to an <iframe mozbrowser> or <iframe mozapp>, we'll
|
||||||
// have to tweak our PreHandleEvent implementation.
|
// GetEventTargetParent implementation.
|
||||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwner);
|
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwner);
|
||||||
if (browserFrame) {
|
if (browserFrame) {
|
||||||
mIsBrowserOrAppFrame = browserFrame->GetReallyIsBrowserOrApp();
|
mIsBrowserOrAppFrame = browserFrame->GetReallyIsBrowserOrApp();
|
||||||
|
|
@ -251,7 +251,7 @@ nsInProcessTabChildGlobal::GetOwnerContent()
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsInProcessTabChildGlobal::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
nsInProcessTabChildGlobal::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
aVisitor.mForceContentDispatch = true;
|
aVisitor.mForceContentDispatch = true;
|
||||||
aVisitor.mCanHandle = true;
|
aVisitor.mCanHandle = true;
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ public:
|
||||||
JS::Handle<JSObject *> aCpows,
|
JS::Handle<JSObject *> aCpows,
|
||||||
nsIPrincipal* aPrincipal) override;
|
nsIPrincipal* aPrincipal) override;
|
||||||
|
|
||||||
virtual nsresult PreHandleEvent(
|
virtual nsresult GetEventTargetParent(
|
||||||
mozilla::EventChainPreVisitor& aVisitor) override;
|
mozilla::EventChainPreVisitor& aVisitor) override;
|
||||||
NS_IMETHOD AddEventListener(const nsAString& aType,
|
NS_IMETHOD AddEventListener(const nsAString& aType,
|
||||||
nsIDOMEventListener* aListener,
|
nsIDOMEventListener* aListener,
|
||||||
|
|
@ -168,7 +168,7 @@ protected:
|
||||||
|
|
||||||
// Is this the message manager for an in-process <iframe mozbrowser> or
|
// Is this the message manager for an in-process <iframe mozbrowser> or
|
||||||
// <iframe mozapp>? This affects where events get sent, so it affects
|
// <iframe mozapp>? This affects where events get sent, so it affects
|
||||||
// PreHandleEvent.
|
// GetEventTargetParent.
|
||||||
bool mIsBrowserOrAppFrame;
|
bool mIsBrowserOrAppFrame;
|
||||||
bool mPreventEventsEscaping;
|
bool mPreventEventsEscaping;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,7 @@ nsWindowRoot::GetContextForEventHandlers(nsresult* aRv)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWindowRoot::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
nsWindowRoot::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
aVisitor.mCanHandle = true;
|
aVisitor.mCanHandle = true;
|
||||||
aVisitor.mForceContentDispatch = true; //FIXME! Bug 329119
|
aVisitor.mForceContentDispatch = true; //FIXME! Bug 329119
|
||||||
|
|
|
||||||
|
|
@ -328,7 +328,7 @@ DOMEventTargetHelper::GetEventHandler(nsIAtom* aType,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
DOMEventTargetHelper::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
DOMEventTargetHelper::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
aVisitor.mCanHandle = true;
|
aVisitor.mCanHandle = true;
|
||||||
aVisitor.mParentTarget = nullptr;
|
aVisitor.mParentTarget = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -248,10 +248,10 @@ NS_DEFINE_STATIC_IID_ACCESSOR(DOMEventTargetHelper,
|
||||||
|
|
||||||
/* Use this macro to declare functions that forward the behavior of this
|
/* Use this macro to declare functions that forward the behavior of this
|
||||||
* interface to another object.
|
* interface to another object.
|
||||||
* This macro doesn't forward PreHandleEvent because sometimes subclasses
|
* This macro doesn't forward GetEventTargetParent because sometimes subclasses
|
||||||
* want to override it.
|
* want to override it.
|
||||||
*/
|
*/
|
||||||
#define NS_FORWARD_NSIDOMEVENTTARGET_NOPREHANDLEEVENT(_to) \
|
#define NS_FORWARD_NSIDOMEVENTTARGET_NOGETEVENTTARGETPARENT(_to) \
|
||||||
NS_IMETHOD AddEventListener(const nsAString & type, nsIDOMEventListener *listener, bool useCapture, bool wantsUntrusted, uint8_t _argc) { \
|
NS_IMETHOD AddEventListener(const nsAString & type, nsIDOMEventListener *listener, bool useCapture, bool wantsUntrusted, uint8_t _argc) { \
|
||||||
return _to AddEventListener(type, listener, useCapture, wantsUntrusted, _argc); \
|
return _to AddEventListener(type, listener, useCapture, wantsUntrusted, _argc); \
|
||||||
} \
|
} \
|
||||||
|
|
|
||||||
|
|
@ -130,13 +130,6 @@ static bool IsEventTargetChrome(EventTarget* aEventTarget,
|
||||||
return isChrome;
|
return isChrome;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH (1 << 0)
|
|
||||||
#define NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT (1 << 1)
|
|
||||||
#define NS_TARGET_CHAIN_MAY_HAVE_MANAGER (1 << 2)
|
|
||||||
#define NS_TARGET_CHAIN_CHECKED_IF_CHROME (1 << 3)
|
|
||||||
#define NS_TARGET_CHAIN_IS_CHROME_CONTENT (1 << 4)
|
|
||||||
|
|
||||||
// EventTargetChainItem represents a single item in the event target chain.
|
// EventTargetChainItem represents a single item in the event target chain.
|
||||||
class EventTargetChainItem
|
class EventTargetChainItem
|
||||||
{
|
{
|
||||||
|
|
@ -144,8 +137,7 @@ private:
|
||||||
explicit EventTargetChainItem(EventTarget* aTarget);
|
explicit EventTargetChainItem(EventTarget* aTarget);
|
||||||
public:
|
public:
|
||||||
EventTargetChainItem()
|
EventTargetChainItem()
|
||||||
: mFlags(0)
|
: mItemFlags(0)
|
||||||
, mItemFlags(0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -153,7 +145,8 @@ public:
|
||||||
EventTarget* aTarget,
|
EventTarget* aTarget,
|
||||||
EventTargetChainItem* aChild = nullptr)
|
EventTargetChainItem* aChild = nullptr)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!aChild || &aChain.ElementAt(aChain.Length() - 1) == aChild);
|
// The last item which can handle the event must be aChild.
|
||||||
|
MOZ_ASSERT(GetLastCanHandleEventTarget(aChain) == aChild);
|
||||||
return new (aChain.AppendElement()) EventTargetChainItem(aTarget);
|
return new (aChain.AppendElement()) EventTargetChainItem(aTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -165,6 +158,38 @@ public:
|
||||||
aChain.RemoveElementAt(lastIndex);
|
aChain.RemoveElementAt(lastIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static EventTargetChainItem* GetFirstCanHandleEventTarget(
|
||||||
|
nsTArray<EventTargetChainItem>& aChain)
|
||||||
|
{
|
||||||
|
return &aChain[GetFirstCanHandleEventTargetIdx(aChain)];
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t GetFirstCanHandleEventTargetIdx(nsTArray<EventTargetChainItem>& aChain)
|
||||||
|
{
|
||||||
|
// aChain[i].PreHandleEventOnly() = true only when the target element wants
|
||||||
|
// PreHandleEvent and set mCanHandle=false. So we find the first element
|
||||||
|
// which can handle the event.
|
||||||
|
for (uint32_t i = 0; i < aChain.Length(); ++i) {
|
||||||
|
if (!aChain[i].PreHandleEventOnly()) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static EventTargetChainItem* GetLastCanHandleEventTarget(
|
||||||
|
nsTArray<EventTargetChainItem>& aChain)
|
||||||
|
{
|
||||||
|
// Fine the last item which can handle the event.
|
||||||
|
for (int32_t i = aChain.Length() - 1; i >= 0; --i) {
|
||||||
|
if (!aChain[i].PreHandleEventOnly()) {
|
||||||
|
return &aChain[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsValid()
|
bool IsValid()
|
||||||
{
|
{
|
||||||
NS_WARNING_ASSERTION(!!(mTarget), "Event target is not valid!");
|
NS_WARNING_ASSERTION(!!(mTarget), "Event target is not valid!");
|
||||||
|
|
@ -183,44 +208,52 @@ public:
|
||||||
|
|
||||||
void SetForceContentDispatch(bool aForce)
|
void SetForceContentDispatch(bool aForce)
|
||||||
{
|
{
|
||||||
if (aForce) {
|
mFlags.mForceContentDispatch = aForce;
|
||||||
mFlags |= NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH;
|
|
||||||
} else {
|
|
||||||
mFlags &= ~NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ForceContentDispatch()
|
bool ForceContentDispatch()
|
||||||
{
|
{
|
||||||
return !!(mFlags & NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH);
|
return mFlags.mForceContentDispatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetWantsWillHandleEvent(bool aWants)
|
void SetWantsWillHandleEvent(bool aWants)
|
||||||
{
|
{
|
||||||
if (aWants) {
|
mFlags.mWantsWillHandleEvent = aWants;
|
||||||
mFlags |= NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT;
|
|
||||||
} else {
|
|
||||||
mFlags &= ~NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WantsWillHandleEvent()
|
bool WantsWillHandleEvent()
|
||||||
{
|
{
|
||||||
return !!(mFlags & NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT);
|
return mFlags.mWantsWillHandleEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetWantsPreHandleEvent(bool aWants)
|
||||||
|
{
|
||||||
|
mFlags.mWantsPreHandleEvent = aWants;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WantsPreHandleEvent()
|
||||||
|
{
|
||||||
|
return mFlags.mWantsPreHandleEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPreHandleEventOnly(bool aWants)
|
||||||
|
{
|
||||||
|
mFlags.mPreHandleEventOnly = aWants;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PreHandleEventOnly()
|
||||||
|
{
|
||||||
|
return mFlags.mPreHandleEventOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetMayHaveListenerManager(bool aMayHave)
|
void SetMayHaveListenerManager(bool aMayHave)
|
||||||
{
|
{
|
||||||
if (aMayHave) {
|
mFlags.mMayHaveManager = aMayHave;
|
||||||
mFlags |= NS_TARGET_CHAIN_MAY_HAVE_MANAGER;
|
|
||||||
} else {
|
|
||||||
mFlags &= ~NS_TARGET_CHAIN_MAY_HAVE_MANAGER;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MayHaveListenerManager()
|
bool MayHaveListenerManager()
|
||||||
{
|
{
|
||||||
return !!(mFlags & NS_TARGET_CHAIN_MAY_HAVE_MANAGER);
|
return mFlags.mMayHaveManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
EventTarget* CurrentTarget()
|
EventTarget* CurrentTarget()
|
||||||
|
|
@ -240,10 +273,15 @@ public:
|
||||||
ELMCreationDetector& aCd);
|
ELMCreationDetector& aCd);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets aVisitor object and calls PreHandleEvent.
|
* Resets aVisitor object and calls GetEventTargetParent.
|
||||||
* Copies mItemFlags and mItemData to the current EventTargetChainItem.
|
* Copies mItemFlags and mItemData to the current EventTargetChainItem.
|
||||||
*/
|
*/
|
||||||
void PreHandleEvent(EventChainPreVisitor& aVisitor);
|
void GetEventTargetParent(EventChainPreVisitor& aVisitor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls PreHandleEvent for those items which called SetWantsPreHandleEvent.
|
||||||
|
*/
|
||||||
|
void PreHandleEvent(EventChainVisitor& aVisitor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the current item in the event target chain has an event listener
|
* If the current item in the event target chain has an event listener
|
||||||
|
|
@ -288,7 +326,34 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsCOMPtr<EventTarget> mTarget;
|
nsCOMPtr<EventTarget> mTarget;
|
||||||
uint16_t mFlags;
|
|
||||||
|
class EventTargetChainFlags
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit EventTargetChainFlags()
|
||||||
|
{
|
||||||
|
SetRawFlags(0);
|
||||||
|
}
|
||||||
|
// Cached flags for each EventTargetChainItem which are set when calling
|
||||||
|
// GetEventTargetParent to create event target chain. They are used to
|
||||||
|
// manage or speedup event dispatching.
|
||||||
|
bool mForceContentDispatch : 1;
|
||||||
|
bool mWantsWillHandleEvent : 1;
|
||||||
|
bool mMayHaveManager : 1;
|
||||||
|
bool mChechedIfChrome : 1;
|
||||||
|
bool mIsChromeContent : 1;
|
||||||
|
bool mWantsPreHandleEvent : 1;
|
||||||
|
bool mPreHandleEventOnly : 1;
|
||||||
|
private:
|
||||||
|
typedef uint32_t RawFlags;
|
||||||
|
void SetRawFlags(RawFlags aRawFlags)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(EventTargetChainFlags) <= sizeof(RawFlags),
|
||||||
|
"EventTargetChainFlags must not be bigger than the RawFlags");
|
||||||
|
memcpy(this, &aRawFlags, sizeof(EventTargetChainFlags));
|
||||||
|
}
|
||||||
|
} mFlags;
|
||||||
|
|
||||||
uint16_t mItemFlags;
|
uint16_t mItemFlags;
|
||||||
nsCOMPtr<nsISupports> mItemData;
|
nsCOMPtr<nsISupports> mItemData;
|
||||||
// Event retargeting must happen whenever mNewTarget is non-null.
|
// Event retargeting must happen whenever mNewTarget is non-null.
|
||||||
|
|
@ -298,36 +363,48 @@ private:
|
||||||
|
|
||||||
bool IsCurrentTargetChrome()
|
bool IsCurrentTargetChrome()
|
||||||
{
|
{
|
||||||
if (!(mFlags & NS_TARGET_CHAIN_CHECKED_IF_CHROME)) {
|
if (!mFlags.mChechedIfChrome) {
|
||||||
mFlags |= NS_TARGET_CHAIN_CHECKED_IF_CHROME;
|
mFlags.mChechedIfChrome = true;
|
||||||
if (IsEventTargetChrome(mTarget)) {
|
if (IsEventTargetChrome(mTarget)) {
|
||||||
mFlags |= NS_TARGET_CHAIN_IS_CHROME_CONTENT;
|
mFlags.mIsChromeContent = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return !!(mFlags & NS_TARGET_CHAIN_IS_CHROME_CONTENT);
|
return mFlags.mIsChromeContent;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
EventTargetChainItem::EventTargetChainItem(EventTarget* aTarget)
|
EventTargetChainItem::EventTargetChainItem(EventTarget* aTarget)
|
||||||
: mTarget(aTarget)
|
: mTarget(aTarget)
|
||||||
, mFlags(0)
|
|
||||||
, mItemFlags(0)
|
, mItemFlags(0)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!aTarget || mTarget == aTarget->GetTargetForEventTargetChain());
|
MOZ_ASSERT(!aTarget || mTarget == aTarget->GetTargetForEventTargetChain());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
EventTargetChainItem::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
EventTargetChainItem::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
aVisitor.Reset();
|
aVisitor.Reset();
|
||||||
Unused << mTarget->PreHandleEvent(aVisitor);
|
Unused << mTarget->GetEventTargetParent(aVisitor);
|
||||||
SetForceContentDispatch(aVisitor.mForceContentDispatch);
|
SetForceContentDispatch(aVisitor.mForceContentDispatch);
|
||||||
SetWantsWillHandleEvent(aVisitor.mWantsWillHandleEvent);
|
SetWantsWillHandleEvent(aVisitor.mWantsWillHandleEvent);
|
||||||
SetMayHaveListenerManager(aVisitor.mMayHaveListenerManager);
|
SetMayHaveListenerManager(aVisitor.mMayHaveListenerManager);
|
||||||
|
SetWantsPreHandleEvent(aVisitor.mWantsPreHandleEvent);
|
||||||
|
SetPreHandleEventOnly(aVisitor.mWantsPreHandleEvent && !aVisitor.mCanHandle);
|
||||||
mItemFlags = aVisitor.mItemFlags;
|
mItemFlags = aVisitor.mItemFlags;
|
||||||
mItemData = aVisitor.mItemData;
|
mItemData = aVisitor.mItemData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EventTargetChainItem::PreHandleEvent(EventChainVisitor& aVisitor)
|
||||||
|
{
|
||||||
|
if (!WantsPreHandleEvent()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
aVisitor.mItemFlags = mItemFlags;
|
||||||
|
aVisitor.mItemData = mItemData;
|
||||||
|
Unused << mTarget->PreHandleEvent(aVisitor);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
EventTargetChainItem::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
EventTargetChainItem::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
|
|
@ -346,12 +423,17 @@ EventTargetChainItem::HandleEventTargetChain(
|
||||||
// Save the target so that it can be restored later.
|
// Save the target so that it can be restored later.
|
||||||
nsCOMPtr<EventTarget> firstTarget = aVisitor.mEvent->mTarget;
|
nsCOMPtr<EventTarget> firstTarget = aVisitor.mEvent->mTarget;
|
||||||
uint32_t chainLength = aChain.Length();
|
uint32_t chainLength = aChain.Length();
|
||||||
|
uint32_t firstCanHandleEventTargetIdx =
|
||||||
|
EventTargetChainItem::GetFirstCanHandleEventTargetIdx(aChain);
|
||||||
|
|
||||||
// Capture
|
// Capture
|
||||||
aVisitor.mEvent->mFlags.mInCapturePhase = true;
|
aVisitor.mEvent->mFlags.mInCapturePhase = true;
|
||||||
aVisitor.mEvent->mFlags.mInBubblingPhase = false;
|
aVisitor.mEvent->mFlags.mInBubblingPhase = false;
|
||||||
for (uint32_t i = chainLength - 1; i > 0; --i) {
|
for (uint32_t i = chainLength - 1; i > firstCanHandleEventTargetIdx; --i) {
|
||||||
EventTargetChainItem& item = aChain[i];
|
EventTargetChainItem& item = aChain[i];
|
||||||
|
if (item.PreHandleEventOnly()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if ((!aVisitor.mEvent->mFlags.mNoContentDispatch ||
|
if ((!aVisitor.mEvent->mFlags.mNoContentDispatch ||
|
||||||
item.ForceContentDispatch()) &&
|
item.ForceContentDispatch()) &&
|
||||||
!aVisitor.mEvent->PropagationStopped()) {
|
!aVisitor.mEvent->PropagationStopped()) {
|
||||||
|
|
@ -373,7 +455,7 @@ EventTargetChainItem::HandleEventTargetChain(
|
||||||
|
|
||||||
// Target
|
// Target
|
||||||
aVisitor.mEvent->mFlags.mInBubblingPhase = true;
|
aVisitor.mEvent->mFlags.mInBubblingPhase = true;
|
||||||
EventTargetChainItem& targetItem = aChain[0];
|
EventTargetChainItem& targetItem = aChain[firstCanHandleEventTargetIdx];
|
||||||
if (!aVisitor.mEvent->PropagationStopped() &&
|
if (!aVisitor.mEvent->PropagationStopped() &&
|
||||||
(!aVisitor.mEvent->mFlags.mNoContentDispatch ||
|
(!aVisitor.mEvent->mFlags.mNoContentDispatch ||
|
||||||
targetItem.ForceContentDispatch())) {
|
targetItem.ForceContentDispatch())) {
|
||||||
|
|
@ -385,8 +467,11 @@ EventTargetChainItem::HandleEventTargetChain(
|
||||||
|
|
||||||
// Bubble
|
// Bubble
|
||||||
aVisitor.mEvent->mFlags.mInCapturePhase = false;
|
aVisitor.mEvent->mFlags.mInCapturePhase = false;
|
||||||
for (uint32_t i = 1; i < chainLength; ++i) {
|
for (uint32_t i = firstCanHandleEventTargetIdx + 1; i < chainLength; ++i) {
|
||||||
EventTargetChainItem& item = aChain[i];
|
EventTargetChainItem& item = aChain[i];
|
||||||
|
if (item.PreHandleEventOnly()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
EventTarget* newTarget = item.GetNewTarget();
|
EventTarget* newTarget = item.GetNewTarget();
|
||||||
if (newTarget) {
|
if (newTarget) {
|
||||||
// Item is at anonymous boundary. Need to retarget for the current item
|
// Item is at anonymous boundary. Need to retarget for the current item
|
||||||
|
|
@ -471,6 +556,28 @@ EventTargetChainItemForChromeTarget(nsTArray<EventTargetChainItem>& aChain,
|
||||||
return etci;
|
return etci;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ EventTargetChainItem*
|
||||||
|
MayRetargetToChromeIfCanNotHandleEvent(
|
||||||
|
nsTArray<EventTargetChainItem>& aChain, EventChainPreVisitor& aPreVisitor,
|
||||||
|
EventTargetChainItem* aTargetEtci, EventTargetChainItem* aChildEtci,
|
||||||
|
nsINode* aContent)
|
||||||
|
{
|
||||||
|
if (!aPreVisitor.mWantsPreHandleEvent) {
|
||||||
|
// Keep EventTargetChainItem if we need to call PreHandleEvent on it.
|
||||||
|
EventTargetChainItem::DestroyLast(aChain, aTargetEtci);
|
||||||
|
}
|
||||||
|
if (aPreVisitor.mAutomaticChromeDispatch && aContent) {
|
||||||
|
// Event target couldn't handle the event. Try to propagate to chrome.
|
||||||
|
EventTargetChainItem* chromeTargetEtci =
|
||||||
|
EventTargetChainItemForChromeTarget(aChain, aContent, aChildEtci);
|
||||||
|
if (chromeTargetEtci) {
|
||||||
|
chromeTargetEtci->GetEventTargetParent(aPreVisitor);
|
||||||
|
return chromeTargetEtci;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/* static */ nsresult
|
/* static */ nsresult
|
||||||
EventDispatcher::Dispatch(nsISupports* aTarget,
|
EventDispatcher::Dispatch(nsISupports* aTarget,
|
||||||
nsPresContext* aPresContext,
|
nsPresContext* aPresContext,
|
||||||
|
|
@ -593,7 +700,6 @@ EventDispatcher::Dispatch(nsISupports* aTarget,
|
||||||
// Create the event target chain item for the event target.
|
// Create the event target chain item for the event target.
|
||||||
EventTargetChainItem* targetEtci =
|
EventTargetChainItem* targetEtci =
|
||||||
EventTargetChainItem::Create(chain, target->GetTargetForEventTargetChain());
|
EventTargetChainItem::Create(chain, target->GetTargetForEventTargetChain());
|
||||||
MOZ_ASSERT(&chain[0] == targetEtci);
|
|
||||||
if (!targetEtci->IsValid()) {
|
if (!targetEtci->IsValid()) {
|
||||||
EventTargetChainItem::DestroyLast(chain, targetEtci);
|
EventTargetChainItem::DestroyLast(chain, targetEtci);
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
@ -631,21 +737,24 @@ EventDispatcher::Dispatch(nsISupports* aTarget,
|
||||||
aEvent->mFlags.mIsBeingDispatched = true;
|
aEvent->mFlags.mIsBeingDispatched = true;
|
||||||
|
|
||||||
// Create visitor object and start event dispatching.
|
// Create visitor object and start event dispatching.
|
||||||
// PreHandleEvent for the original target.
|
// GetEventTargetParent for the original target.
|
||||||
nsEventStatus status = aEventStatus ? *aEventStatus : nsEventStatus_eIgnore;
|
nsEventStatus status = aEventStatus ? *aEventStatus : nsEventStatus_eIgnore;
|
||||||
EventChainPreVisitor preVisitor(aPresContext, aEvent, aDOMEvent, status,
|
EventChainPreVisitor preVisitor(aPresContext, aEvent, aDOMEvent, status,
|
||||||
isInAnon);
|
isInAnon);
|
||||||
targetEtci->PreHandleEvent(preVisitor);
|
targetEtci->GetEventTargetParent(preVisitor);
|
||||||
|
|
||||||
if (!preVisitor.mCanHandle && preVisitor.mAutomaticChromeDispatch && content) {
|
if (!preVisitor.mCanHandle) {
|
||||||
// Event target couldn't handle the event. Try to propagate to chrome.
|
targetEtci = MayRetargetToChromeIfCanNotHandleEvent(chain, preVisitor,
|
||||||
EventTargetChainItem::DestroyLast(chain, targetEtci);
|
targetEtci, nullptr,
|
||||||
targetEtci = EventTargetChainItemForChromeTarget(chain, content);
|
content);
|
||||||
NS_ENSURE_STATE(targetEtci);
|
|
||||||
MOZ_ASSERT(&chain[0] == targetEtci);
|
|
||||||
targetEtci->PreHandleEvent(preVisitor);
|
|
||||||
}
|
}
|
||||||
if (preVisitor.mCanHandle) {
|
if (!preVisitor.mCanHandle) {
|
||||||
|
// The original target and chrome target (mAutomaticChromeDispatch=true)
|
||||||
|
// can not handle the event but we still have to call their PreHandleEvent.
|
||||||
|
for (uint32_t i = 0; i < chain.Length(); ++i) {
|
||||||
|
chain[i].PreHandleEvent(preVisitor);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// At least the original target can handle the event.
|
// At least the original target can handle the event.
|
||||||
// Setting the retarget to the |target| simplifies retargeting code.
|
// Setting the retarget to the |target| simplifies retargeting code.
|
||||||
nsCOMPtr<EventTarget> t = do_QueryInterface(aEvent->mTarget);
|
nsCOMPtr<EventTarget> t = do_QueryInterface(aEvent->mTarget);
|
||||||
|
|
@ -670,29 +779,22 @@ EventDispatcher::Dispatch(nsISupports* aTarget,
|
||||||
parentEtci->SetNewTarget(preVisitor.mEventTargetAtParent);
|
parentEtci->SetNewTarget(preVisitor.mEventTargetAtParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
parentEtci->PreHandleEvent(preVisitor);
|
parentEtci->GetEventTargetParent(preVisitor);
|
||||||
if (preVisitor.mCanHandle) {
|
if (preVisitor.mCanHandle) {
|
||||||
topEtci = parentEtci;
|
topEtci = parentEtci;
|
||||||
} else {
|
} else {
|
||||||
EventTargetChainItem::DestroyLast(chain, parentEtci);
|
nsCOMPtr<nsINode> disabledTarget = do_QueryInterface(parentTarget);
|
||||||
parentEtci = nullptr;
|
parentEtci = MayRetargetToChromeIfCanNotHandleEvent(chain,
|
||||||
if (preVisitor.mAutomaticChromeDispatch && content) {
|
preVisitor,
|
||||||
// Even if the current target can't handle the event, try to
|
parentEtci,
|
||||||
// propagate to chrome.
|
topEtci,
|
||||||
nsCOMPtr<nsINode> disabledTarget = do_QueryInterface(parentTarget);
|
disabledTarget);
|
||||||
if (disabledTarget) {
|
if (parentEtci && preVisitor.mCanHandle) {
|
||||||
parentEtci = EventTargetChainItemForChromeTarget(chain,
|
EventTargetChainItem* item =
|
||||||
disabledTarget,
|
EventTargetChainItem::GetFirstCanHandleEventTarget(chain);
|
||||||
topEtci);
|
item->SetNewTarget(parentTarget);
|
||||||
if (parentEtci) {
|
topEtci = parentEtci;
|
||||||
parentEtci->PreHandleEvent(preVisitor);
|
continue;
|
||||||
if (preVisitor.mCanHandle) {
|
|
||||||
chain[0].SetNewTarget(parentTarget);
|
|
||||||
topEtci = parentEtci;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -706,7 +808,11 @@ EventDispatcher::Dispatch(nsISupports* aTarget,
|
||||||
targets[i] = chain[i].CurrentTarget()->GetTargetForDOMEvent();
|
targets[i] = chain[i].CurrentTarget()->GetTargetForDOMEvent();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Event target chain is created. Handle the chain.
|
// Event target chain is created. PreHandle the chain.
|
||||||
|
for (uint32_t i = 0; i < chain.Length(); ++i) {
|
||||||
|
chain[i].PreHandleEvent(preVisitor);
|
||||||
|
}
|
||||||
|
// Handle the chain.
|
||||||
EventChainPostVisitor postVisitor(preVisitor);
|
EventChainPostVisitor postVisitor(preVisitor);
|
||||||
EventTargetChainItem::HandleEventTargetChain(chain, postVisitor,
|
EventTargetChainItem::HandleEventTargetChain(chain, postVisitor,
|
||||||
aCallback, cd);
|
aCallback, cd);
|
||||||
|
|
|
||||||
|
|
@ -31,14 +31,14 @@ class EventTarget;
|
||||||
* About event dispatching:
|
* About event dispatching:
|
||||||
* When either EventDispatcher::Dispatch or
|
* When either EventDispatcher::Dispatch or
|
||||||
* EventDispatcher::DispatchDOMEvent is called an event target chain is
|
* EventDispatcher::DispatchDOMEvent is called an event target chain is
|
||||||
* created. EventDispatcher creates the chain by calling PreHandleEvent
|
* created. EventDispatcher creates the chain by calling GetEventTargetParent
|
||||||
* on each event target and the creation continues until either the mCanHandle
|
* on each event target and the creation continues until either the mCanHandle
|
||||||
* member of the EventChainPreVisitor object is false or the mParentTarget
|
* member of the EventChainPreVisitor object is false or the mParentTarget
|
||||||
* does not point to a new target. The event target chain is created in the
|
* does not point to a new target. The event target chain is created in the
|
||||||
* heap.
|
* heap.
|
||||||
*
|
*
|
||||||
* If the event needs retargeting, mEventTargetAtParent must be set in
|
* If the event needs retargeting, mEventTargetAtParent must be set in
|
||||||
* PreHandleEvent.
|
* GetEventTargetParent.
|
||||||
*
|
*
|
||||||
* The capture, target and bubble phases of the event dispatch are handled
|
* The capture, target and bubble phases of the event dispatch are handled
|
||||||
* by iterating through the event target chain. Iteration happens twice,
|
* by iterating through the event target chain. Iteration happens twice,
|
||||||
|
|
@ -86,7 +86,7 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bits for items in the event target chain.
|
* Bits for items in the event target chain.
|
||||||
* Set in PreHandleEvent() and used in PostHandleEvent().
|
* Set in GetEventTargetParent() and used in PostHandleEvent().
|
||||||
*
|
*
|
||||||
* @note These bits are different for each item in the event target chain.
|
* @note These bits are different for each item in the event target chain.
|
||||||
* It is up to the Pre/PostHandleEvent implementation to decide how to
|
* It is up to the Pre/PostHandleEvent implementation to decide how to
|
||||||
|
|
@ -98,7 +98,7 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data for items in the event target chain.
|
* Data for items in the event target chain.
|
||||||
* Set in PreHandleEvent() and used in PostHandleEvent().
|
* Set in GetEventTargetParent() and used in PostHandleEvent().
|
||||||
*
|
*
|
||||||
* @note This data is different for each item in the event target chain.
|
* @note This data is different for each item in the event target chain.
|
||||||
* It is up to the Pre/PostHandleEvent implementation to decide how to
|
* It is up to the Pre/PostHandleEvent implementation to decide how to
|
||||||
|
|
@ -123,6 +123,7 @@ public:
|
||||||
, mOriginalTargetIsInAnon(aIsInAnon)
|
, mOriginalTargetIsInAnon(aIsInAnon)
|
||||||
, mWantsWillHandleEvent(false)
|
, mWantsWillHandleEvent(false)
|
||||||
, mMayHaveListenerManager(true)
|
, mMayHaveListenerManager(true)
|
||||||
|
, mWantsPreHandleEvent(false)
|
||||||
, mParentTarget(nullptr)
|
, mParentTarget(nullptr)
|
||||||
, mEventTargetAtParent(nullptr)
|
, mEventTargetAtParent(nullptr)
|
||||||
{
|
{
|
||||||
|
|
@ -137,13 +138,14 @@ public:
|
||||||
mForceContentDispatch = false;
|
mForceContentDispatch = false;
|
||||||
mWantsWillHandleEvent = false;
|
mWantsWillHandleEvent = false;
|
||||||
mMayHaveListenerManager = true;
|
mMayHaveListenerManager = true;
|
||||||
|
mWantsPreHandleEvent = false;
|
||||||
mParentTarget = nullptr;
|
mParentTarget = nullptr;
|
||||||
mEventTargetAtParent = nullptr;
|
mEventTargetAtParent = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Member that must be set in PreHandleEvent by event targets. If set to false,
|
* Member that must be set in GetEventTargetParent by event targets. If set to
|
||||||
* indicates that this event target will not be handling the event and
|
* false, indicates that this event target will not be handling the event and
|
||||||
* construction of the event target chain is complete. The target that sets
|
* construction of the event target chain is complete. The target that sets
|
||||||
* mCanHandle to false is NOT included in the event target chain.
|
* mCanHandle to false is NOT included in the event target chain.
|
||||||
*/
|
*/
|
||||||
|
|
@ -170,7 +172,7 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* true if the original target of the event is inside anonymous content.
|
* true if the original target of the event is inside anonymous content.
|
||||||
* This is set before calling PreHandleEvent on event targets.
|
* This is set before calling GetEventTargetParent on event targets.
|
||||||
*/
|
*/
|
||||||
bool mOriginalTargetIsInAnon;
|
bool mOriginalTargetIsInAnon;
|
||||||
|
|
||||||
|
|
@ -182,10 +184,16 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If it is known that the current target doesn't have a listener manager
|
* If it is known that the current target doesn't have a listener manager
|
||||||
* when PreHandleEvent is called, set this to false.
|
* when GetEventTargetParent is called, set this to false.
|
||||||
*/
|
*/
|
||||||
bool mMayHaveListenerManager;
|
bool mMayHaveListenerManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not nsIDOMEventTarget::PreHandleEvent will be called. Default is
|
||||||
|
* false;
|
||||||
|
*/
|
||||||
|
bool mWantsPreHandleEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parent item in the event target chain.
|
* Parent item in the event target chain.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -185,3 +185,4 @@ skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
|
||||||
[test_bug687787.html]
|
[test_bug687787.html]
|
||||||
[test_bug1298970.html]
|
[test_bug1298970.html]
|
||||||
[test_bug1304044.html]
|
[test_bug1304044.html]
|
||||||
|
[test_bug1305458.html]
|
||||||
|
|
|
||||||
50
dom/events/test/test_bug1305458.html
Normal file
50
dom/events/test/test_bug1305458.html
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1305458
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test for Bug 1305458</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
<style>
|
||||||
|
input[type=number] {
|
||||||
|
-moz-appearance: textfield;
|
||||||
|
}
|
||||||
|
input[type=number]:focus,
|
||||||
|
input[type=number]:hover {
|
||||||
|
-moz-appearance: number-input;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body onload="doTest()">
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1305458">Mozilla Bug 1305458</a>
|
||||||
|
<input id="test_input" type="number">
|
||||||
|
<div id="test_div">bar</div>
|
||||||
|
<script>
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
var change_count = 0;
|
||||||
|
function doTest() {
|
||||||
|
let input = document.getElementById("test_input");
|
||||||
|
let div = document.getElementById("test_div");
|
||||||
|
input.addEventListener("change", () => {
|
||||||
|
++change_count;
|
||||||
|
}, false);
|
||||||
|
// mouse hover
|
||||||
|
input.focus();
|
||||||
|
synthesizeMouse(input, 1, 1, {type: "mousemove"});
|
||||||
|
synthesizeKey("1", {});
|
||||||
|
input.blur();
|
||||||
|
is(change_count, 1, "input should fire change when blur");
|
||||||
|
|
||||||
|
input.focus();
|
||||||
|
synthesizeMouse(div, 1, 1, {type: "mousemove"});
|
||||||
|
synthesizeKey("1", {});
|
||||||
|
input.blur();
|
||||||
|
is(change_count, 2, "input should fire change when blur");
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -252,9 +252,9 @@ HTMLAnchorElement::IsHTMLFocusable(bool aWithMouse,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLAnchorElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
HTMLAnchorElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
return PreHandleEventForAnchors(aVisitor);
|
return GetEventTargetParentForAnchors(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,8 @@ public:
|
||||||
bool aNullParent = true) override;
|
bool aNullParent = true) override;
|
||||||
virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) 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(
|
virtual nsresult PostHandleEvent(
|
||||||
EventChainPostVisitor& aVisitor) override;
|
EventChainPostVisitor& aVisitor) override;
|
||||||
virtual bool IsLink(nsIURI** aURI) const override;
|
virtual bool IsLink(nsIURI** aURI) const override;
|
||||||
|
|
|
||||||
|
|
@ -81,9 +81,9 @@ HTMLAreaElement::SetTarget(const nsAString& aValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLAreaElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
HTMLAreaElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
return PreHandleEventForAnchors(aVisitor);
|
return GetEventTargetParentForAnchors(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,8 @@ public:
|
||||||
// nsIDOMHTMLAreaElement
|
// nsIDOMHTMLAreaElement
|
||||||
NS_DECL_NSIDOMHTMLAREAELEMENT
|
NS_DECL_NSIDOMHTMLAREAELEMENT
|
||||||
|
|
||||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
virtual nsresult GetEventTargetParent(
|
||||||
|
EventChainPreVisitor& aVisitor) override;
|
||||||
virtual nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override;
|
virtual nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override;
|
||||||
virtual bool IsLink(nsIURI** aURI) const override;
|
virtual bool IsLink(nsIURI** aURI) const override;
|
||||||
virtual void GetLinkTarget(nsAString& aTarget) override;
|
virtual void GetLinkTarget(nsAString& aTarget) override;
|
||||||
|
|
|
||||||
|
|
@ -207,7 +207,7 @@ HTMLButtonElement::IsDisabledForEvents(EventMessage aMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLButtonElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
HTMLButtonElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
aVisitor.mCanHandle = false;
|
aVisitor.mCanHandle = false;
|
||||||
if (IsDisabledForEvents(aVisitor.mEvent->mMessage)) {
|
if (IsDisabledForEvents(aVisitor.mEvent->mMessage)) {
|
||||||
|
|
@ -235,7 +235,7 @@ HTMLButtonElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
|
return nsGenericHTMLElement::GetEventTargetParent(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,8 @@ public:
|
||||||
virtual void FieldSetDisabledChanged(bool aNotify) override;
|
virtual void FieldSetDisabledChanged(bool aNotify) override;
|
||||||
|
|
||||||
// nsIDOMEventTarget
|
// nsIDOMEventTarget
|
||||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
virtual nsresult GetEventTargetParent(
|
||||||
|
EventChainPreVisitor& aVisitor) override;
|
||||||
virtual nsresult PostHandleEvent(
|
virtual nsresult PostHandleEvent(
|
||||||
EventChainPostVisitor& aVisitor) override;
|
EventChainPostVisitor& aVisitor) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -574,7 +574,7 @@ HTMLCanvasElement::CopyInnerTo(Element* aDest)
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult HTMLCanvasElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
nsresult HTMLCanvasElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
if (aVisitor.mEvent->mClass == eMouseEventClass) {
|
if (aVisitor.mEvent->mClass == eMouseEventClass) {
|
||||||
WidgetMouseEventBase* evt = (WidgetMouseEventBase*)aVisitor.mEvent;
|
WidgetMouseEventBase* evt = (WidgetMouseEventBase*)aVisitor.mEvent;
|
||||||
|
|
@ -592,7 +592,7 @@ nsresult HTMLCanvasElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||||
aVisitor.mCanHandle = true;
|
aVisitor.mCanHandle = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
|
return nsGenericHTMLElement::GetEventTargetParent(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsChangeHint
|
nsChangeHint
|
||||||
|
|
|
||||||
|
|
@ -312,7 +312,8 @@ public:
|
||||||
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
|
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
|
||||||
nsresult CopyInnerTo(mozilla::dom::Element* aDest);
|
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
|
* Helpers called by various users of Canvas
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ HTMLFieldSetElement::IsDisabledForEvents(EventMessage aMessage)
|
||||||
|
|
||||||
// nsIContent
|
// nsIContent
|
||||||
nsresult
|
nsresult
|
||||||
HTMLFieldSetElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
HTMLFieldSetElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
// Do not process any DOM events if the element is disabled.
|
// Do not process any DOM events if the element is disabled.
|
||||||
aVisitor.mCanHandle = false;
|
aVisitor.mCanHandle = false;
|
||||||
|
|
@ -78,7 +78,7 @@ HTMLFieldSetElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nsGenericHTMLFormElement::PreHandleEvent(aVisitor);
|
return nsGenericHTMLFormElement::GetEventTargetParent(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,8 @@ public:
|
||||||
NS_DECL_NSIDOMHTMLFIELDSETELEMENT
|
NS_DECL_NSIDOMHTMLFIELDSETELEMENT
|
||||||
|
|
||||||
// nsIContent
|
// nsIContent
|
||||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
virtual nsresult GetEventTargetParent(
|
||||||
|
EventChainPreVisitor& aVisitor) override;
|
||||||
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||||
const nsAttrValue* aValue, bool aNotify) override;
|
const nsAttrValue* aValue, bool aNotify) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -489,7 +489,7 @@ HTMLFormElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLFormElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
HTMLFormElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
aVisitor.mWantsWillHandleEvent = true;
|
aVisitor.mWantsWillHandleEvent = true;
|
||||||
if (aVisitor.mEvent->mOriginalTarget == static_cast<nsIContent*>(this)) {
|
if (aVisitor.mEvent->mOriginalTarget == static_cast<nsIContent*>(this)) {
|
||||||
|
|
@ -513,7 +513,7 @@ HTMLFormElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||||
mGeneratingReset = true;
|
mGeneratingReset = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
|
return nsGenericHTMLElement::GetEventTargetParent(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,8 @@ public:
|
||||||
nsIAtom* aAttribute,
|
nsIAtom* aAttribute,
|
||||||
const nsAString& aValue,
|
const nsAString& aValue,
|
||||||
nsAttrValue& aResult) override;
|
nsAttrValue& aResult) override;
|
||||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
virtual nsresult GetEventTargetParent(
|
||||||
|
EventChainPreVisitor& aVisitor) override;
|
||||||
virtual nsresult WillHandleEvent(
|
virtual nsresult WillHandleEvent(
|
||||||
EventChainPostVisitor& aVisitor) override;
|
EventChainPostVisitor& aVisitor) override;
|
||||||
virtual nsresult PostHandleEvent(
|
virtual nsresult PostHandleEvent(
|
||||||
|
|
|
||||||
|
|
@ -437,7 +437,7 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLImageElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
HTMLImageElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
// We handle image element with attribute ismap in its corresponding frame
|
// We handle image element with attribute ismap in its corresponding frame
|
||||||
// element. Set mMultipleActionsPrevented here to prevent the click event
|
// element. Set mMultipleActionsPrevented here to prevent the click event
|
||||||
|
|
@ -446,7 +446,7 @@ HTMLImageElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||||
if (mouseEvent && mouseEvent->IsLeftClickEvent() && IsMap()) {
|
if (mouseEvent && mouseEvent->IsLeftClickEvent() && IsMap()) {
|
||||||
mouseEvent->mFlags.mMultipleActionsPrevented = true;
|
mouseEvent->mFlags.mMultipleActionsPrevented = true;
|
||||||
}
|
}
|
||||||
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
|
return nsGenericHTMLElement::GetEventTargetParent(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,8 @@ public:
|
||||||
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
|
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
|
||||||
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() 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;
|
bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,8 @@ namespace dom {
|
||||||
#define NS_CONTROL_TYPE(bits) ((bits) & ~( \
|
#define NS_CONTROL_TYPE(bits) ((bits) & ~( \
|
||||||
NS_OUTER_ACTIVATE_EVENT | NS_ORIGINAL_CHECKED_VALUE | NS_NO_CONTENT_DISPATCH | \
|
NS_OUTER_ACTIVATE_EVENT | NS_ORIGINAL_CHECKED_VALUE | NS_NO_CONTENT_DISPATCH | \
|
||||||
NS_ORIGINAL_INDETERMINATE_VALUE))
|
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:
|
// whether textfields should be selected once focused:
|
||||||
// -1: no, 1: yes, 0: uninitialized
|
// -1: no, 1: yes, 0: uninitialized
|
||||||
|
|
@ -3738,7 +3740,7 @@ HTMLInputElement::IsDisabledForEvents(EventMessage aMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
HTMLInputElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
// Do not process any DOM events if the element is disabled
|
// Do not process any DOM events if the element is disabled
|
||||||
aVisitor.mCanHandle = false;
|
aVisitor.mCanHandle = false;
|
||||||
|
|
@ -3755,7 +3757,7 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||||
|
|
||||||
//FIXME Allow submission etc. also when there is no prescontext, Bug 329509.
|
//FIXME Allow submission etc. also when there is no prescontext, Bug 329509.
|
||||||
if (!aVisitor.mPresContext) {
|
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
|
// 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.
|
// Fire onchange (if necessary), before we do the blur, bug 357684.
|
||||||
if (aVisitor.mEvent->mMessage == eBlur) {
|
if (aVisitor.mEvent->mMessage == eBlur) {
|
||||||
// Experimental mobile types rely on the system UI to prevent users to not
|
// We set NS_PRE_HANDLE_BLUR_EVENT here and handle it in PreHandleEvent to
|
||||||
// set invalid values but we have to be extra-careful. Especially if the
|
// prevent breaking event target chain creation.
|
||||||
// option has been enabled on desktop.
|
aVisitor.mWantsPreHandleEvent = true;
|
||||||
if (IsExperimentalMobileType(mType)) {
|
aVisitor.mItemFlags |= NS_PRE_HANDLE_BLUR_EVENT;
|
||||||
nsAutoString aValue;
|
|
||||||
GetValueInternal(aValue);
|
|
||||||
nsresult rv =
|
|
||||||
SetValueInternal(aValue, nsTextEditorState::eSetValue_Internal);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
}
|
|
||||||
FireChangeEventIfNeeded();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mType == NS_FORM_INPUT_RANGE &&
|
if (mType == NS_FORM_INPUT_RANGE &&
|
||||||
(aVisitor.mEvent->mMessage == eFocus ||
|
(aVisitor.mEvent->mMessage == eFocus ||
|
||||||
aVisitor.mEvent->mMessage == eBlur)) {
|
aVisitor.mEvent->mMessage == eBlur)) {
|
||||||
// Just as nsGenericHTMLFormElementWithState::PreHandleEvent calls
|
// Just as nsGenericHTMLFormElementWithState::GetEventTargetParent calls
|
||||||
// nsIFormControlFrame::SetFocus, we handle focus here.
|
// nsIFormControlFrame::SetFocus, we handle focus here.
|
||||||
nsIFrame* frame = GetPrimaryFrame();
|
nsIFrame* frame = GetPrimaryFrame();
|
||||||
if (frame) {
|
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
|
// We do this after calling the base class' GetEventTargetParent so that
|
||||||
// nsIContent::PreHandleEvent doesn't reset any change we make to mCanHandle.
|
// nsIContent::GetEventTargetParent doesn't reset any change we make to
|
||||||
|
// mCanHandle.
|
||||||
if (mType == NS_FORM_INPUT_NUMBER &&
|
if (mType == NS_FORM_INPUT_NUMBER &&
|
||||||
aVisitor.mEvent->IsTrusted() &&
|
aVisitor.mEvent->IsTrusted() &&
|
||||||
aVisitor.mEvent->mOriginalTarget != this) {
|
aVisitor.mEvent->mOriginalTarget != this) {
|
||||||
|
|
@ -3987,18 +3983,10 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||||
}
|
}
|
||||||
if (textControl && aVisitor.mEvent->mOriginalTarget == textControl) {
|
if (textControl && aVisitor.mEvent->mOriginalTarget == textControl) {
|
||||||
if (aVisitor.mEvent->mMessage == eEditorInput) {
|
if (aVisitor.mEvent->mMessage == eEditorInput) {
|
||||||
// Propogate the anon text control's new value to our HTMLInputElement:
|
aVisitor.mWantsPreHandleEvent = true;
|
||||||
nsAutoString value;
|
// We set NS_PRE_HANDLE_INPUT_EVENT here and handle it in PreHandleEvent
|
||||||
numberControlFrame->GetValueOfAnonTextControl(value);
|
// to prevent breaking event target chain creation.
|
||||||
numberControlFrame->HandlingInputEvent(true);
|
aVisitor.mItemFlags |= NS_PRE_HANDLE_INPUT_EVENT;
|
||||||
nsWeakFrame weakNumberControlFrame(numberControlFrame);
|
|
||||||
rv = SetValueInternal(value,
|
|
||||||
nsTextEditorState::eSetValue_BySetUserInput |
|
|
||||||
nsTextEditorState::eSetValue_Notify);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
if (weakNumberControlFrame.IsAlive()) {
|
|
||||||
numberControlFrame->HandlingInputEvent(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (aVisitor.mEvent->mMessage == eFormChange) {
|
else if (aVisitor.mEvent->mMessage == eFormChange) {
|
||||||
// We cancel the DOM 'change' event that is fired for any change to our
|
// We cancel the DOM 'change' event that is fired for any change to our
|
||||||
|
|
@ -4037,6 +4025,50 @@ HTMLInputElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||||
return rv;
|
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
|
void
|
||||||
HTMLInputElement::StartRangeThumbDrag(WidgetGUIEvent* aEvent)
|
HTMLInputElement::StartRangeThumbDrag(WidgetGUIEvent* aEvent)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,9 @@ public:
|
||||||
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
|
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
|
||||||
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() 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(
|
virtual nsresult PostHandleEvent(
|
||||||
EventChainPostVisitor& aVisitor) override;
|
EventChainPostVisitor& aVisitor) override;
|
||||||
void PostHandleEventForRangeThumb(EventChainPostVisitor& aVisitor);
|
void PostHandleEventForRangeThumb(EventChainPostVisitor& aVisitor);
|
||||||
|
|
|
||||||
|
|
@ -421,9 +421,9 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLLinkElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
HTMLLinkElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
return PreHandleEventForAnchors(aVisitor);
|
return GetEventTargetParentForAnchors(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,8 @@ public:
|
||||||
void UpdateImport();
|
void UpdateImport();
|
||||||
|
|
||||||
// nsIDOMEventTarget
|
// nsIDOMEventTarget
|
||||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
virtual nsresult GetEventTargetParent(
|
||||||
|
EventChainPreVisitor& aVisitor) override;
|
||||||
virtual nsresult PostHandleEvent(
|
virtual nsresult PostHandleEvent(
|
||||||
EventChainPostVisitor& aVisitor) override;
|
EventChainPostVisitor& aVisitor) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -252,7 +252,7 @@ HTMLMenuItemElement::SetChecked(bool aChecked)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLMenuItemElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
HTMLMenuItemElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
if (aVisitor.mEvent->mMessage == eMouseClick) {
|
if (aVisitor.mEvent->mMessage == eMouseClick) {
|
||||||
|
|
||||||
|
|
@ -283,7 +283,7 @@ HTMLMenuItemElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||||
aVisitor.mItemFlags |= mType;
|
aVisitor.mItemFlags |= mType;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
|
return nsGenericHTMLElement::GetEventTargetParent(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@ public:
|
||||||
// nsIDOMHTMLMenuItemElement
|
// nsIDOMHTMLMenuItemElement
|
||||||
NS_DECL_NSIDOMHTMLMENUITEMELEMENT
|
NS_DECL_NSIDOMHTMLMENUITEMELEMENT
|
||||||
|
|
||||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
virtual nsresult GetEventTargetParent(
|
||||||
|
EventChainPreVisitor& aVisitor) override;
|
||||||
virtual nsresult PostHandleEvent(
|
virtual nsresult PostHandleEvent(
|
||||||
EventChainPostVisitor& aVisitor) override;
|
EventChainPostVisitor& aVisitor) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ NS_IMPL_STRING_ATTR(HTMLOptGroupElement, Label, label)
|
||||||
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLOptGroupElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
HTMLOptGroupElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
aVisitor.mCanHandle = false;
|
aVisitor.mCanHandle = false;
|
||||||
// Do not process any DOM events if the element is disabled
|
// Do not process any DOM events if the element is disabled
|
||||||
|
|
@ -66,7 +66,7 @@ HTMLOptGroupElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
|
return nsGenericHTMLElement::GetEventTargetParent(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
Element*
|
Element*
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,8 @@ public:
|
||||||
virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override;
|
virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override;
|
||||||
|
|
||||||
// nsIContent
|
// nsIContent
|
||||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
virtual nsresult GetEventTargetParent(
|
||||||
|
EventChainPreVisitor& aVisitor) override;
|
||||||
|
|
||||||
virtual EventStates IntrinsicState() const override;
|
virtual EventStates IntrinsicState() const override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1442,14 +1442,14 @@ HTMLSelectElement::IsDisabledForEvents(EventMessage aMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLSelectElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
HTMLSelectElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
aVisitor.mCanHandle = false;
|
aVisitor.mCanHandle = false;
|
||||||
if (IsDisabledForEvents(aVisitor.mEvent->mMessage)) {
|
if (IsDisabledForEvents(aVisitor.mEvent->mMessage)) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nsGenericHTMLFormElementWithState::PreHandleEvent(aVisitor);
|
return nsGenericHTMLFormElementWithState::GetEventTargetParent(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
||||||
|
|
@ -278,7 +278,8 @@ public:
|
||||||
virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
// nsIContent
|
// nsIContent
|
||||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
virtual nsresult GetEventTargetParent(
|
||||||
|
EventChainPreVisitor& aVisitor) override;
|
||||||
virtual nsresult PostHandleEvent(
|
virtual nsresult PostHandleEvent(
|
||||||
EventChainPostVisitor& aVisitor) override;
|
EventChainPostVisitor& aVisitor) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -506,7 +506,7 @@ HTMLTextAreaElement::IsDisabledForEvents(EventMessage aMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
HTMLTextAreaElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
HTMLTextAreaElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
aVisitor.mCanHandle = false;
|
aVisitor.mCanHandle = false;
|
||||||
if (IsDisabledForEvents(aVisitor.mEvent->mMessage)) {
|
if (IsDisabledForEvents(aVisitor.mEvent->mMessage)) {
|
||||||
|
|
@ -534,11 +534,22 @@ HTMLTextAreaElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||||
aVisitor.mEvent->mFlags.mNoContentDispatch = false;
|
aVisitor.mEvent->mFlags.mNoContentDispatch = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fire onchange (if necessary), before we do the blur, bug 370521.
|
|
||||||
if (aVisitor.mEvent->mMessage == eBlur) {
|
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);
|
return nsGenericHTMLFormElementWithState::PreHandleEvent(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,9 @@ public:
|
||||||
int32_t aModType) const override;
|
int32_t aModType) const override;
|
||||||
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) 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(
|
virtual nsresult PostHandleEvent(
|
||||||
EventChainPostVisitor& aVisitor) override;
|
EventChainPostVisitor& aVisitor) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -607,16 +607,16 @@ nsGenericHTMLElement::CheckHandleEventForAnchorsPreconditions(
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsGenericHTMLElement::PreHandleEventForAnchors(EventChainPreVisitor& aVisitor)
|
nsGenericHTMLElement::GetEventTargetParentForAnchors(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
nsresult rv = nsGenericHTMLElementBase::PreHandleEvent(aVisitor);
|
nsresult rv = nsGenericHTMLElementBase::GetEventTargetParent(aVisitor);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
if (!CheckHandleEventForAnchorsPreconditions(aVisitor)) {
|
if (!CheckHandleEventForAnchorsPreconditions(aVisitor)) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return PreHandleEventForLinks(aVisitor);
|
return GetEventTargetParentForLinks(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
@ -2081,7 +2081,19 @@ nsGenericHTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
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()) {
|
if (aVisitor.mEvent->IsTrusted()) {
|
||||||
switch (aVisitor.mEvent->mMessage) {
|
switch (aVisitor.mEvent->mMessage) {
|
||||||
|
|
@ -2105,7 +2117,6 @@ nsGenericHTMLFormElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
|
return nsGenericHTMLElement::PreHandleEvent(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -498,7 +498,8 @@ public:
|
||||||
*/
|
*/
|
||||||
bool CheckHandleEventForAnchorsPreconditions(
|
bool CheckHandleEventForAnchorsPreconditions(
|
||||||
mozilla::EventChainVisitor& aVisitor);
|
mozilla::EventChainVisitor& aVisitor);
|
||||||
nsresult PreHandleEventForAnchors(mozilla::EventChainPreVisitor& aVisitor);
|
nsresult GetEventTargetParentForAnchors(
|
||||||
|
mozilla::EventChainPreVisitor& aVisitor);
|
||||||
nsresult PostHandleEventForAnchors(mozilla::EventChainPostVisitor& aVisitor);
|
nsresult PostHandleEventForAnchors(mozilla::EventChainPostVisitor& aVisitor);
|
||||||
bool IsHTMLLink(nsIURI** aURI) const;
|
bool IsHTMLLink(nsIURI** aURI) const;
|
||||||
|
|
||||||
|
|
@ -1219,8 +1220,10 @@ public:
|
||||||
virtual IMEState GetDesiredIMEState() override;
|
virtual IMEState GetDesiredIMEState() override;
|
||||||
virtual mozilla::EventStates IntrinsicState() const override;
|
virtual mozilla::EventStates IntrinsicState() const override;
|
||||||
|
|
||||||
virtual nsresult PreHandleEvent(
|
virtual nsresult GetEventTargetParent(
|
||||||
mozilla::EventChainPreVisitor& aVisitor) override;
|
mozilla::EventChainPreVisitor& aVisitor) override;
|
||||||
|
virtual nsresult PreHandleEvent(
|
||||||
|
mozilla::EventChainVisitor& aVisitor) override;
|
||||||
|
|
||||||
virtual bool IsDisabled() const override;
|
virtual bool IsDisabled() const override;
|
||||||
|
|
||||||
|
|
@ -1307,7 +1310,7 @@ protected:
|
||||||
static bool FormIdUpdated(Element* aOldElement, Element* aNewElement,
|
static bool FormIdUpdated(Element* aOldElement, Element* aNewElement,
|
||||||
void* aData);
|
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,
|
bool IsElementDisabledForEvents(mozilla::EventMessage aMessage,
|
||||||
nsIFrame* aFrame);
|
nsIFrame* aFrame);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ IDBFileHandle::Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
IDBFileHandle::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
IDBFileHandle::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
AssertIsOnOwningThread();
|
AssertIsOnOwningThread();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ public:
|
||||||
|
|
||||||
// nsIDOMEventTarget
|
// nsIDOMEventTarget
|
||||||
virtual nsresult
|
virtual nsresult
|
||||||
PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
|
||||||
|
|
||||||
// WrapperCache
|
// WrapperCache
|
||||||
virtual JSObject*
|
virtual JSObject*
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(IDBFileRequest, DOMRequest,
|
||||||
mFileHandle)
|
mFileHandle)
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
IDBFileRequest::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
IDBFileRequest::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
AssertIsOnOwningThread();
|
AssertIsOnOwningThread();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ public:
|
||||||
|
|
||||||
// nsIDOMEventTarget
|
// nsIDOMEventTarget
|
||||||
virtual nsresult
|
virtual nsresult
|
||||||
PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
|
||||||
|
|
||||||
// nsWrapperCache
|
// nsWrapperCache
|
||||||
virtual JSObject*
|
virtual JSObject*
|
||||||
|
|
|
||||||
|
|
@ -449,7 +449,7 @@ NS_IMPL_ADDREF_INHERITED(IDBRequest, IDBWrapperCache)
|
||||||
NS_IMPL_RELEASE_INHERITED(IDBRequest, IDBWrapperCache)
|
NS_IMPL_RELEASE_INHERITED(IDBRequest, IDBWrapperCache)
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
IDBRequest::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
IDBRequest::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
AssertIsOnOwningThread();
|
AssertIsOnOwningThread();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ public:
|
||||||
|
|
||||||
// nsIDOMEventTarget
|
// nsIDOMEventTarget
|
||||||
virtual nsresult
|
virtual nsresult
|
||||||
PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
|
||||||
|
|
||||||
void
|
void
|
||||||
GetSource(Nullable<OwningIDBObjectStoreOrIDBIndexOrIDBCursor>& aSource) const;
|
GetSource(Nullable<OwningIDBObjectStoreOrIDBIndexOrIDBCursor>& aSource) const;
|
||||||
|
|
|
||||||
|
|
@ -996,7 +996,7 @@ IDBTransaction::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
IDBTransaction::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
IDBTransaction::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
AssertIsOnOwningThread();
|
AssertIsOnOwningThread();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -314,7 +314,7 @@ public:
|
||||||
|
|
||||||
// nsIDOMEventTarget
|
// nsIDOMEventTarget
|
||||||
virtual nsresult
|
virtual nsresult
|
||||||
PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IDBTransaction(IDBDatabase* aDatabase,
|
IDBTransaction(IDBDatabase* aDatabase,
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
using mozilla::dom::Nullable;
|
using mozilla::dom::Nullable;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
class EventChainVisitor;
|
||||||
class EventChainPostVisitor;
|
class EventChainPostVisitor;
|
||||||
class EventChainPreVisitor;
|
class EventChainPreVisitor;
|
||||||
class EventListenerManager;
|
class EventListenerManager;
|
||||||
|
|
@ -224,7 +225,19 @@ interface nsIDOMEventTarget : nsISupports
|
||||||
* @note Only EventDispatcher should call this method.
|
* @note Only EventDispatcher should call this method.
|
||||||
*/
|
*/
|
||||||
[noscript, nostdcall]
|
[noscript, nostdcall]
|
||||||
void PreHandleEvent(in EventChainPreVisitorRef aVisitor);
|
void GetEventTargetParent(in EventChainPreVisitorRef aVisitor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called before the capture phase of the event flow and after event target
|
||||||
|
* chain creation. This is used to handle those stuffs must be executed before
|
||||||
|
* dispatch event to DOM
|
||||||
|
*/
|
||||||
|
%{C++
|
||||||
|
virtual nsresult PreHandleEvent(mozilla::EventChainVisitor& aVisitor)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If EventChainPreVisitor.mWantsWillHandleEvent is set PR_TRUE,
|
* If EventChainPreVisitor.mWantsWillHandleEvent is set PR_TRUE,
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
PreHandleEvent(EventChainPreVisitor& aVisitor) override
|
GetEventTargetParent(EventChainPreVisitor& aVisitor) override
|
||||||
{
|
{
|
||||||
aVisitor.mForceContentDispatch = true;
|
aVisitor.mForceContentDispatch = true;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
|
||||||
|
|
@ -919,12 +919,12 @@ nsMathMLElement::MapMathMLAttributesInto(const nsMappedAttributes* aAttributes,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsMathMLElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
nsMathMLElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
nsresult rv = Element::PreHandleEvent(aVisitor);
|
nsresult rv = Element::GetEventTargetParent(aVisitor);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
return PreHandleEventForLinks(aVisitor);
|
return GetEventTargetParentForLinks(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ public:
|
||||||
static void MapMathMLAttributesInto(const nsMappedAttributes* aAttributes,
|
static void MapMathMLAttributesInto(const nsMappedAttributes* aAttributes,
|
||||||
nsRuleData* aRuleData);
|
nsRuleData* aRuleData);
|
||||||
|
|
||||||
virtual nsresult PreHandleEvent(
|
virtual nsresult GetEventTargetParent(
|
||||||
mozilla::EventChainPreVisitor& aVisitor) override;
|
mozilla::EventChainPreVisitor& aVisitor) override;
|
||||||
virtual nsresult PostHandleEvent(
|
virtual nsresult PostHandleEvent(
|
||||||
mozilla::EventChainPostVisitor& aVisitor) override;
|
mozilla::EventChainPostVisitor& aVisitor) override;
|
||||||
|
|
|
||||||
|
|
@ -84,12 +84,12 @@ SVGAElement::Href()
|
||||||
// nsINode methods
|
// nsINode methods
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
SVGAElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
SVGAElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
nsresult rv = Element::PreHandleEvent(aVisitor);
|
nsresult rv = Element::GetEventTargetParent(aVisitor);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
return PreHandleEventForLinks(aVisitor);
|
return GetEventTargetParentForLinks(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,8 @@ public:
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGAElement, SVGAElementBase)
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGAElement, SVGAElementBase)
|
||||||
|
|
||||||
// nsINode interface methods
|
// nsINode interface methods
|
||||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
virtual nsresult GetEventTargetParent(
|
||||||
|
EventChainPreVisitor& aVisitor) override;
|
||||||
virtual nsresult PostHandleEvent(
|
virtual nsresult PostHandleEvent(
|
||||||
EventChainPostVisitor& aVisitor) override;
|
EventChainPostVisitor& aVisitor) override;
|
||||||
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
|
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
|
||||||
|
|
|
||||||
|
|
@ -589,7 +589,7 @@ SVGSVGElement::IsAttributeMapped(const nsIAtom* name) const
|
||||||
// nsIContent methods:
|
// nsIContent methods:
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
SVGSVGElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
SVGSVGElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
if (aVisitor.mEvent->mMessage == eSVGLoad) {
|
if (aVisitor.mEvent->mMessage == eSVGLoad) {
|
||||||
if (mTimedDocumentRoot) {
|
if (mTimedDocumentRoot) {
|
||||||
|
|
@ -600,7 +600,7 @@ SVGSVGElement::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||||
AnimationNeedsResample();
|
AnimationNeedsResample();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SVGSVGElementBase::PreHandleEvent(aVisitor);
|
return SVGSVGElementBase::GetEventTargetParent(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,8 @@ public:
|
||||||
|
|
||||||
// nsIContent interface
|
// nsIContent interface
|
||||||
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
|
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
|
||||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
virtual nsresult GetEventTargetParent(
|
||||||
|
EventChainPreVisitor& aVisitor) override;
|
||||||
|
|
||||||
virtual bool IsEventAttributeName(nsIAtom* aName) override;
|
virtual bool IsEventAttributeName(nsIAtom* aName) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,7 @@ SharedWorker::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
SharedWorker::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
SharedWorker::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||||
{
|
{
|
||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
|
|
||||||
|
|
@ -200,5 +200,5 @@ SharedWorker::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DOMEventTargetHelper::PreHandleEvent(aVisitor);
|
return DOMEventTargetHelper::GetEventTargetParent(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ public:
|
||||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
virtual nsresult
|
virtual nsresult
|
||||||
PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
|
||||||
|
|
||||||
WorkerPrivate*
|
WorkerPrivate*
|
||||||
GetWorkerPrivate() const
|
GetWorkerPrivate() const
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,8 @@ uint32_t nsXULPrototypeAttribute::gNumCacheSets;
|
||||||
uint32_t nsXULPrototypeAttribute::gNumCacheFills;
|
uint32_t nsXULPrototypeAttribute::gNumCacheFills;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define NS_DISPATCH_XUL_COMMAND (1 << 0)
|
||||||
|
|
||||||
class nsXULElementTearoff final : public nsIFrameLoaderOwner
|
class nsXULElementTearoff final : public nsIFrameLoaderOwner
|
||||||
{
|
{
|
||||||
~nsXULElementTearoff() {}
|
~nsXULElementTearoff() {}
|
||||||
|
|
@ -1236,17 +1238,65 @@ nsXULElement::List(FILE* out, int32_t aIndent) const
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsXULElement::IsEventStoppedFromAnonymousScrollbar(EventMessage aMessage)
|
||||||
|
{
|
||||||
|
return (IsRootOfNativeAnonymousSubtree() &&
|
||||||
|
IsAnyOfXULElements(nsGkAtoms::scrollbar, nsGkAtoms::scrollcorner) &&
|
||||||
|
(aMessage == eMouseClick || aMessage == eMouseDoubleClick ||
|
||||||
|
aMessage == eXULCommand || aMessage == eContextMenu ||
|
||||||
|
aMessage == eDragStart));
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
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
|
aVisitor.mForceContentDispatch = true; //FIXME! Bug 329119
|
||||||
if (IsRootOfNativeAnonymousSubtree() &&
|
if (IsEventStoppedFromAnonymousScrollbar(aVisitor.mEvent->mMessage)) {
|
||||||
(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)) {
|
|
||||||
// Don't propagate these events from native anonymous scrollbar.
|
// Don't propagate these events from native anonymous scrollbar.
|
||||||
aVisitor.mCanHandle = true;
|
aVisitor.mCanHandle = true;
|
||||||
aVisitor.mParentTarget = nullptr;
|
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
|
// See if we have a command elt. If so, we execute on the command
|
||||||
// instead of on our content element.
|
// instead of on our content element.
|
||||||
nsAutoString command;
|
nsAutoString command;
|
||||||
if (xulEvent && GetAttr(kNameSpaceID_None, nsGkAtoms::command, command) &&
|
if (xulEvent &&
|
||||||
|
GetAttr(kNameSpaceID_None, nsGkAtoms::command, command) &&
|
||||||
!command.IsEmpty()) {
|
!command.IsEmpty()) {
|
||||||
// Stop building the event target chain for the original event.
|
// Stop building the event target chain for the original event.
|
||||||
// We don't want it to propagate to any DOM nodes.
|
// We don't want it to propagate to any DOM nodes.
|
||||||
aVisitor.mCanHandle = false;
|
aVisitor.mCanHandle = false;
|
||||||
aVisitor.mAutomaticChromeDispatch = false;
|
aVisitor.mAutomaticChromeDispatch = false;
|
||||||
|
// Dispatch XUL command in PreHandleEvent to prevent it breaks event
|
||||||
// XXX sXBL/XBL2 issue! Owner or current document?
|
// target chain creation
|
||||||
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(GetUncomposedDoc()));
|
aVisitor.mWantsPreHandleEvent = true;
|
||||||
NS_ENSURE_STATE(domDoc);
|
aVisitor.mItemFlags |= NS_DISPATCH_XUL_COMMAND;
|
||||||
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");
|
|
||||||
}
|
|
||||||
return NS_OK;
|
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);
|
return nsStyledElement::PreHandleEvent(aVisitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -355,9 +355,10 @@ public:
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULElement, nsStyledElement)
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULElement, nsStyledElement)
|
||||||
|
|
||||||
// nsINode
|
// nsINode
|
||||||
virtual nsresult PreHandleEvent(
|
virtual nsresult GetEventTargetParent(
|
||||||
mozilla::EventChainPreVisitor& aVisitor) override;
|
mozilla::EventChainPreVisitor& aVisitor) override;
|
||||||
|
virtual nsresult PreHandleEvent(
|
||||||
|
mozilla::EventChainVisitor& aVisitor) override;
|
||||||
// nsIContent
|
// nsIContent
|
||||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||||
nsIContent* aBindingParent,
|
nsIContent* aBindingParent,
|
||||||
|
|
@ -689,6 +690,11 @@ protected:
|
||||||
virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
|
virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
void MaybeUpdatePrivateLifetime();
|
void MaybeUpdatePrivateLifetime();
|
||||||
|
|
||||||
|
bool IsEventStoppedFromAnonymousScrollbar(mozilla::EventMessage aMessage);
|
||||||
|
|
||||||
|
nsresult DispatchXULCommand(const mozilla::EventChainVisitor& aVisitor,
|
||||||
|
nsAutoString& aCommand);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // nsXULElement_h__
|
#endif // nsXULElement_h__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue