#399: passive event listener support M1266066

This commit is contained in:
Cameron Kaiser 2017-12-17 20:18:13 -08:00
parent fbde989ca7
commit 034fda860a
5 changed files with 41 additions and 17 deletions

View File

@ -522,6 +522,14 @@ Event::PreventDefaultInternal(bool aCalledByDefaultHandler)
if (!mEvent->mFlags.mCancelable) {
return;
}
if (mEvent->mFlags.mInPassiveListener) {
#if DEBUG
// XXX: There should be a warning here, but we don't have the string.
// https://hg.mozilla.org/mozilla-central/rev/cda76e80a47c
fprintf(stderr, "** PreventDefaultInternal called on Passive Listener\n");
#endif
return;
}
mEvent->mFlags.mDefaultPrevented = true;

View File

@ -250,7 +250,7 @@ EventListenerManager::AddEventListenerInternal(
listener = &mListeners.ElementAt(i);
// mListener == aListenerHolder is the last one, since it can be a bit slow.
if (listener->mListenerIsHandler == aHandler &&
listener->mFlags == aFlags &&
listener->mFlags.EqualsForAddition(aFlags) &&
EVENT_TYPE_EQUALS(listener, aEventMessage, aTypeAtom, aTypeString,
aAllEvents) &&
listener->mListener == aListenerHolder) {
@ -409,7 +409,7 @@ EventListenerManager::AddEventListenerInternal(
}
}
if (IsApzAwareEvent(aTypeAtom)) {
if (IsApzAwareListener(listener)) {
nsCOMPtr<nsINode> node = do_QueryInterface(mTarget);
if (node) {
node->SetMayHaveApzAwareListeners();
@ -545,7 +545,7 @@ EventListenerManager::RemoveEventListenerInternal(
aAllEvents)) {
++typeCount;
if (listener->mListener == aListenerHolder &&
listener->mFlags.EqualsIgnoringTrustness(aFlags)) {
listener->mFlags.EqualsForRemoval(aFlags)) {
RefPtr<EventListenerManager> kungFuDeathGrip(this);
mListeners.RemoveElementAt(i);
--count;
@ -1152,9 +1152,11 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
}
}
aEvent->mFlags.mInPassiveListener = listener->mFlags.mPassive;
if (NS_FAILED(HandleEventSubType(listener, *aDOMEvent, aCurrentTarget))) {
aEvent->mFlags.mExceptionHasBeenRisen = true;
}
aEvent->mFlags.mInPassiveListener = false;
if (needsEndEventMarker) {
timelines->AddMarkerForDocShell(
@ -1205,9 +1207,12 @@ EventListenerManager::AddEventListener(
bool aWantsUntrusted)
{
EventListenerFlags flags;
flags.mCapture =
aOptions.IsBoolean() ? aOptions.GetAsBoolean()
: aOptions.GetAsAddEventListenerOptions().mCapture;
if (aOptions.IsBoolean()) {
flags.mCapture = aOptions.GetAsBoolean();
} else {
flags.mCapture = aOptions.GetAsAddEventListenerOptions().mCapture;
flags.mPassive = aOptions.GetAsAddEventListenerOptions().mPassive;
}
flags.mAllowUntrustedEvents = aWantsUntrusted;
return AddEventListenerByType(aListenerHolder, aType, flags);
}
@ -1542,13 +1547,19 @@ EventListenerManager::HasApzAwareListeners()
uint32_t count = mListeners.Length();
for (uint32_t i = 0; i < count; ++i) {
Listener* listener = &mListeners.ElementAt(i);
if (IsApzAwareEvent(listener->mTypeAtom)) {
if (IsApzAwareListener(listener)) {
return true;
}
}
return false;
}
bool
EventListenerManager::IsApzAwareListener(Listener* aListener)
{
return !aListener->mFlags.mPassive && IsApzAwareEvent(aListener->mTypeAtom);
}
bool
EventListenerManager::IsApzAwareEvent(nsIAtom* aEvent)
{

View File

@ -58,31 +58,32 @@ public:
// If mAllowUntrustedEvents is true, the listener is listening to the
// untrusted events too.
bool mAllowUntrustedEvents : 1;
// If mPassive is true, the listener will not be calling preventDefault on the
// event. (If it does call preventDefault, we should ignore it).
bool mPassive : 1;
EventListenerFlags() :
mListenerIsJSListener(false),
mCapture(false), mInSystemGroup(false), mAllowUntrustedEvents(false)
mCapture(false), mInSystemGroup(false), mAllowUntrustedEvents(false),
mPassive(false)
{
}
bool Equals(const EventListenerFlags& aOther) const
bool EqualsForAddition(const EventListenerFlags& aOther) const
{
return (mCapture == aOther.mCapture &&
mInSystemGroup == aOther.mInSystemGroup &&
mListenerIsJSListener == aOther.mListenerIsJSListener &&
mAllowUntrustedEvents == aOther.mAllowUntrustedEvents);
// Don't compare mPassive
}
bool EqualsIgnoringTrustness(const EventListenerFlags& aOther) const
bool EqualsForRemoval(const EventListenerFlags& aOther) const
{
return (mCapture == aOther.mCapture &&
mInSystemGroup == aOther.mInSystemGroup &&
mListenerIsJSListener == aOther.mListenerIsJSListener);
}
bool operator==(const EventListenerFlags& aOther) const
{
return Equals(aOther);
// Don't compare mAllowUntrustedEvents or mPassive
}
};
@ -444,7 +445,7 @@ public:
dom::EventTarget* GetTarget() { return mTarget; }
bool HasApzAwareListeners();
bool IsApzAwareListener(Listener* aListener);
bool IsApzAwareEvent(nsIAtom* aEvent);
protected:

View File

@ -16,7 +16,8 @@ dictionary EventListenerOptions {
};
dictionary AddEventListenerOptions : EventListenerOptions {
// boolean passive = false;
boolean passive = false;
// XXX: this is bug 1287706 and follow-on 1367372
// boolean once = false;
};

View File

@ -115,6 +115,9 @@ public:
// perform its associated action. This is currently only relevant for
// wheel and touch events.
bool mHandledByAPZ : 1;
// True if the event is currently being handled by an event listener that
// was registered as a passive listener.
bool mInPassiveListener: 1;
// If the event is being handled in target phase, returns true.
inline bool InTargetPhase() const